示例#1
0
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            HeaderInfo Header = new HeaderInfo();

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

            bool result = readHeader(source, ref Header);

            // Process data if loaded and header valid
            if (result && StreamUtils.StringEqualsArr(TWIN_ID, Header.ID))
            {
                isValid = true;
                // Fill properties with header data
                channelsArrangement = getChannelArrangement(Header);
                bitrate             = getBitRate(Header);
                sampleRate          = GetSampleRate(Header);
                duration            = getDuration(Header);
                // Get tag information and fill properties
                readTag(source, Header, readTagParams);

                AudioDataOffset = source.BaseStream.Position;
                AudioDataSize   = sizeInfo.FileSize - sizeInfo.APESize - sizeInfo.ID3v1Size - AudioDataOffset;
            }
            return(result);
        }
示例#2
0
        private void testGenericAudio(
            string resource,
            int duration,
            int bitrate,
            int samplerate,
            bool isVbr,
            int codecFamily,
            ChannelsArrangement channelsArrangement,
            string formatName,
            int alternate = 0)
        {
            ConsoleLogger log         = new ConsoleLogger();
            string        theResource = TestUtils.GetResourceLocationRoot() + resource;

            IAudioDataIO theReader = AudioDataIOFactory.GetInstance().GetFromPath(theResource, alternate);

            Assert.IsNotInstanceOfType(theReader, typeof(ATL.AudioData.IO.DummyReader));

            AudioDataManager manager = new AudioDataManager(theReader);

            manager.ReadFromFile();

            Assert.AreEqual(duration, (int)Math.Round(theReader.Duration));
            Assert.AreEqual(bitrate, (int)Math.Round(theReader.BitRate));
            Assert.AreEqual(samplerate, theReader.SampleRate);
            Assert.AreEqual(theReader.IsVBR, isVbr);
            Assert.AreEqual(codecFamily, theReader.CodecFamily);
            Assert.AreEqual(channelsArrangement, theReader.ChannelsArrangement);
            Assert.AreEqual(formatName, theReader.AudioFormat.Name);
        }
示例#3
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;
            resetData();
            source.BaseStream.Seek(sizeInfo.ID3v2Size, SeekOrigin.Begin);

            bool result = false;

            if (TTA_SIGNATURE.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                isValid = true;

                audioFormat         = source.ReadUInt16();
                channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(source.ReadUInt16());
                bitsPerSample       = source.ReadUInt16();
                sampleRate          = source.ReadUInt32();
                samplesSize         = source.ReadUInt32();
                cRC32 = source.ReadUInt32();

                bitrate  = (double)(sizeInfo.FileSize - sizeInfo.TotalTagSize) * 8.0 / ((double)samplesSize * 1000.0 / sampleRate);
                duration = (double)samplesSize * 1000.0 / sampleRate;

                result = true;
            }

            return(result);
        }
示例#4
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);
        }
示例#5
0
        private void readChannelLayoutChunk(BinaryReader source)
        {
            uint channelLayout = StreamUtils.DecodeBEUInt32(source.ReadBytes(4));

            // we don't need anything else

            if (channelsMapping.ContainsKey(channelLayout))
            {
                channelsArrangement = channelsMapping[channelLayout];
            }
        }
示例#6
0
        // ---------- CONSTRUCTORS & INITIALIZERS

        protected void resetData()
        {
            sampleRate          = 0;
            duration            = 0;
            bitrate             = 0;
            isVbr               = false;
            codecFamily         = 0;
            channelsPerFrame    = 0;
            channelsArrangement = null;
            secondsPerByte      = 0;
        }
示例#7
0
        // Read ADIF header data
        private void readADIF(BinaryReader Source)
        {
            int Position;

            Position = (int)(sizeInfo.ID3v2Size * 8 + 32);
            if (0 == StreamUtils.ReadBits(Source, Position, 1))
            {
                Position += 3;
            }
            else
            {
                Position += 75;
            }
            if (0 == StreamUtils.ReadBits(Source, Position, 1))
            {
                bitrateTypeID = AAC_BITRATE_TYPE_CBR;
            }
            else
            {
                bitrateTypeID = AAC_BITRATE_TYPE_VBR;
            }

            Position++;

            bitrate = (int)StreamUtils.ReadBits(Source, Position, 23);

            if (AAC_BITRATE_TYPE_CBR == bitrateTypeID)
            {
                Position += 51;
            }
            else
            {
                Position += 31;
            }

            Position += 2;

            uint channels = 1;

            sampleRate          = SAMPLE_RATE[StreamUtils.ReadBits(Source, Position, 4)];
            Position           += 4;
            channels           += StreamUtils.ReadBits(Source, Position, 4);
            Position           += 4;
            channels           += StreamUtils.ReadBits(Source, Position, 4);
            Position           += 4;
            channels           += StreamUtils.ReadBits(Source, Position, 4);
            Position           += 4;
            channels           += StreamUtils.ReadBits(Source, Position, 2);
            channelsArrangement = ChannelsArrangements.GuessFromChannelNumber((int)channels);
        }
示例#8
0
        // Read ADTS header data
        private void readADTS(BinaryReader Source)
        {
            int frames    = 0;
            int totalSize = 0;
            int position;

            do
            {
                frames++;
                position = (int)(sizeInfo.ID3v2Size + totalSize) * 8;

                if (StreamUtils.ReadBits(Source, position, 12) != 0xFFF)
                {
                    break;
                }

                position += 18;

                sampleRate = SAMPLE_RATE[StreamUtils.ReadBits(Source, position, 4)];
                position  += 5;

                uint channels = StreamUtils.ReadBits(Source, position, 3);
                channelsArrangement = ChannelsArrangements.GuessFromChannelNumber((int)channels);

                position += 7;

                totalSize += (int)StreamUtils.ReadBits(Source, position, 13);
                position  += 13;

                if (0x7FF == StreamUtils.ReadBits(Source, position, 11))
                {
                    bitrateTypeID = AAC_BITRATE_TYPE_VBR;
                }
                else
                {
                    bitrateTypeID = AAC_BITRATE_TYPE_CBR;
                }

                if (AAC_BITRATE_TYPE_CBR == bitrateTypeID)
                {
                    break;
                }
            }while (Source.BaseStream.Length > sizeInfo.ID3v2Size + totalSize);
            bitrate = (int)Math.Round(8 * totalSize / 1024.0 / frames * sampleRate);
        }
示例#9
0
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            fileData = new FileData();

            resetData();
            bool result = readData(source, readTagParams);

            // Process data if loaded and valid
            if (result && isValid(fileData))
            {
                channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(fileData.Channels);
                sampleRate          = fileData.SampleRate;
                bitrate             = (sizeInfo.FileSize - sizeInfo.TotalTagSize - fileData.HeaderSize) * 8.0 / duration;
                isVBR      = (WMA_GSM_VBR_ID == fileData.FormatTag);
                isLossless = (WMA_LOSSLESS_ID == fileData.FormatTag);
            }

            return(result);
        }
示例#10
0
        // 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);
        }
示例#11
0
文件: DSF.cs 项目: jda808/atldotnet
        public bool Read(BinaryReader source, AudioDataManager.SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            this.sizeInfo = sizeInfo;
            bool result = false;

            resetData();

            source.BaseStream.Seek(0, SeekOrigin.Begin);
            if (DSD_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                source.BaseStream.Seek(16, SeekOrigin.Current); // Chunk size and file size
                id3v2Offset = source.ReadInt64();

                if (FMT_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
                {
                    source.BaseStream.Seek(8, SeekOrigin.Current); // Chunk size

                    formatVersion = source.ReadInt32();

                    if (formatVersion > 1)
                    {
                        LogDelegator.GetLogDelegate()(Log.LV_ERROR, "DSF format version " + formatVersion + " not supported");
                        return(result);
                    }

                    isValid = true;

                    source.BaseStream.Seek(8, SeekOrigin.Current); // Format ID (4), Channel type (4)

                    uint channels = source.ReadUInt32();
                    switch (channels)
                    {
                    case 1: channelsArrangement = MONO; break;

                    case 2: channelsArrangement = STEREO; break;

                    case 3: channelsArrangement = ISO_3_0_0; break;

                    case 4: channelsArrangement = QUAD; break;

                    case 5: channelsArrangement = LRCLFE; break;

                    case 6: channelsArrangement = ISO_3_2_0; break;

                    case 7: channelsArrangement = ISO_3_2_1; break;

                    default: channelsArrangement = UNKNOWN; break;
                    }

                    sampleRate = source.ReadUInt32();
                    bits       = source.ReadUInt32();

                    ulong sampleCount = source.ReadUInt64();

                    duration = (double)sampleCount * 1000.0 / sampleRate;
                    bitrate  = Math.Round(((double)(sizeInfo.FileSize - source.BaseStream.Position)) * 8 / duration); //time to calculate average bitrate

                    result = true;
                }

                // Load tag if exists
                if (id3v2Offset > 0)
                {
                    if (readTagParams.PrepareForWriting)
                    {
                        id3v2StructureHelper.AddZone(id3v2Offset, (int)(source.BaseStream.Length - id3v2Offset));
                        id3v2StructureHelper.AddSize(12, source.BaseStream.Length);
                        id3v2StructureHelper.AddIndex(20, id3v2Offset);
                    }
                }
                else
                {
                    id3v2Offset = 0; // Switch status to "tried to read, but nothing found"

                    if (readTagParams.PrepareForWriting)
                    {
                        // Add EOF zone for future tag writing
                        id3v2StructureHelper.AddZone(source.BaseStream.Length, 0);
                        id3v2StructureHelper.AddSize(12, source.BaseStream.Length);
                        id3v2StructureHelper.AddIndex(20, source.BaseStream.Length);
                    }
                }
            }

            return(result);
        }
示例#12
0
        protected override bool read(BinaryReader source, ReadTagParams readTagParams)
        {
            ResetData();
            source.BaseStream.Seek(0, SeekOrigin.Begin);

            bool result         = readFileHeader(source);
            long cursorPos      = source.BaseStream.Position;
            long audioChunkSize = 0;

            // Iterate through chunks
            while (cursorPos < source.BaseStream.Length)
            {
                string chunkType = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
                long   chunkSize = StreamUtils.DecodeBEInt64(source.ReadBytes(8));

                if (readTagParams.PrepareForWriting)
                {
                    structureHelper.AddZone(cursorPos, chunkSize + 12, chunkType);
                }

                switch (chunkType)
                {
                case CHUNK_AUDIO_DESC:
                    readAudioDescriptionChunk(source);
                    break;

                case CHUNK_CHANNEL_LAYOUT:
                    readChannelLayoutChunk(source);
                    break;

                case CHUNK_COOKIE:
                case CHUNK_UMID:
                    if (readTagParams.PrepareForWriting || readTagParams.ReadAllMetaFrames)
                    {
                        readStringChunk(source, chunkType, chunkSize);
                    }
                    break;

                case CHUNK_STRINGS:
                    if (readTagParams.PrepareForWriting || readTagParams.ReadAllMetaFrames)
                    {
                        readStringsChunk(source);
                    }
                    break;

                case CHUNK_INFO:
                    readInfoChunk(source, readTagParams.PrepareForWriting || readTagParams.ReadAllMetaFrames);
                    break;

                case CHUNK_AUDIO:
                    AudioDataOffset = cursorPos;
                    audioChunkSize  = chunkSize;
                    AudioDataSize   = chunkSize + 12;
                    if (secondsPerByte > 0)
                    {
                        duration = chunkSize * secondsPerByte * 1000;
                    }
                    break;

                case CHUNK_PACKET_TABLE:
                    if (0 == secondsPerByte)
                    {
                        readPaktChunk(source);
                    }
                    break;
                }
                source.BaseStream.Seek(cursorPos + chunkSize + 12, SeekOrigin.Begin);
                cursorPos = source.BaseStream.Position;
            }
            bitrate = audioChunkSize * 8d / duration;
            if (null == channelsArrangement)
            {
                if (1 == channelsPerFrame)
                {
                    channelsArrangement = MONO;
                }
                else if (2 == channelsPerFrame)
                {
                    channelsArrangement = STEREO;
                }
                else
                {
                    channelsArrangement = new ChannelsArrangement((int)channelsPerFrame, "Custom layout (" + channelsPerFrame + " channels)");
                }
            }

            return(result);
        }
示例#13
0
        protected void Update(bool readEmbeddedPictures = false)
        {
            if ((null == Path) || (0 == Path.Length))
            {
                return;
            }

            // TODO when tag is not available, customize by naming options // tracks (...)
            if (null == stream)
            {
                fileIO = new AudioFileIO(Path, readEmbeddedPictures, Settings.ReadAllMetaFrames);
            }
            else
            {
                fileIO = new AudioFileIO(stream, mimeType, readEmbeddedPictures, Settings.ReadAllMetaFrames);
            }

            Title = fileIO.Title;
            if (Settings.UseFileNameWhenNoTitle && (null == Title || "" == Title))
            {
                Title = System.IO.Path.GetFileNameWithoutExtension(Path);
            }
            Artist                   = Utils.ProtectValue(fileIO.Artist);
            Composer                 = Utils.ProtectValue(fileIO.Composer);
            Comment                  = Utils.ProtectValue(fileIO.Comment);
            Genre                    = Utils.ProtectValue(fileIO.Genre);
            OriginalArtist           = Utils.ProtectValue(fileIO.OriginalArtist);
            OriginalAlbum            = Utils.ProtectValue(fileIO.OriginalAlbum);
            Description              = Utils.ProtectValue(fileIO.GeneralDescription);
            Copyright                = Utils.ProtectValue(fileIO.Copyright);
            Publisher                = Utils.ProtectValue(fileIO.Publisher);
            AlbumArtist              = Utils.ProtectValue(fileIO.AlbumArtist);
            Conductor                = Utils.ProtectValue(fileIO.Conductor);
            Date                     = fileIO.Date;
            Year                     = fileIO.IntYear;
            Album                    = fileIO.Album;
            TrackNumber              = fileIO.Track;
            TrackTotal               = fileIO.TrackTotal;
            DiscNumber               = fileIO.Disc;
            DiscTotal                = fileIO.DiscTotal;
            ChaptersTableDescription = Utils.ProtectValue(fileIO.ChaptersTableDescription);

            Bitrate     = fileIO.IntBitRate;
            CodecFamily = fileIO.CodecFamily;
            DurationMs  = fileIO.Duration;
#pragma warning disable CS0618 // Obsolete
            Rating = fileIO.Rating;
#pragma warning restore CS0618 // Obsolete
            Popularity          = fileIO.Popularity;
            IsVBR               = fileIO.IsVBR;
            SampleRate          = fileIO.SampleRate;
            ChannelsArrangement = fileIO.ChannelsArrangement;

            Chapters = fileIO.Chapters;
            Lyrics   = fileIO.Lyrics;

            AdditionalFields        = fileIO.AdditionalFields;
            initialAdditionalFields = fileIO.AdditionalFields.Keys;

            PictureTokens = new List <PictureInfo>(fileIO.PictureTokens);

            if (readEmbeddedPictures)
            {
                foreach (PictureInfo picInfo in fileIO.EmbeddedPictures)
                {
                    picInfo.ComputePicHash();
                    currentEmbeddedPictures.Add(picInfo);

                    PictureInfo initialPicInfo = new PictureInfo(picInfo, false);
                    initialEmbeddedPictures.Add(initialPicInfo);
                }
            }

            if (!readEmbeddedPictures && currentEmbeddedPictures != null)
            {
                currentEmbeddedPictures.Clear();
                initialEmbeddedPictures.Clear();
                currentEmbeddedPictures = null;
                initialEmbeddedPictures = null;
            }
        }
示例#14
0
        private bool _ReadV4(BinaryReader r)
        {
            WavPackHeader4 wvh4 = new WavPackHeader4();

            byte[] EncBuf = new byte[4096];
            int    tempo;
            byte   encoderbyte;

            bool result = false;


            wvh4.Reset();

            wvh4.ckID          = r.ReadChars(4);
            wvh4.ckSize        = r.ReadUInt32();
            wvh4.version       = r.ReadUInt16();
            wvh4.track_no      = r.ReadByte();
            wvh4.index_no      = r.ReadByte();
            wvh4.total_samples = r.ReadUInt32();
            wvh4.block_index   = r.ReadUInt32();
            wvh4.block_samples = r.ReadUInt32();
            wvh4.flags         = r.ReadUInt32();
            wvh4.crc           = r.ReadUInt32();

            if (StreamUtils.StringEqualsArr("wvpk", wvh4.ckID))  // wavpack header found  -- TODO handle exceptions better
            {
                result              = true;
                version             = (wvh4.version >> 8);
                channelsArrangement = ChannelsArrangements.GuessFromChannelNumber((int)(2 - (wvh4.flags & 4)));

                bits       = (int)((wvh4.flags & 3) * 16); // bytes stored flag
                samples    = wvh4.total_samples;
                bSamples   = wvh4.block_samples;
                sampleRate = (int)((wvh4.flags & (0x1F << 23)) >> 23);
                if ((sampleRate > 14) || (sampleRate < 0))
                {
                    sampleRate = 44100;
                }
                else
                {
                    sampleRate = sample_rates[sampleRate];
                }

                if (8 == (wvh4.flags & 8))  // hybrid flag
                {
                    encoder     = "hybrid lossy";
                    codecFamily = AudioDataIOFactory.CF_LOSSY;
                }
                else
                { //if (2 == (wvh4.flags & 2) )  {  // lossless flag
                    encoder     = "lossless";
                    codecFamily = AudioDataIOFactory.CF_LOSSLESS;
                }

                /*
                 *                      if ((wvh4.flags & 0x20) > 0)  // MODE_HIGH
                 *                      {
                 *                        FEncoder = FEncoder + " (high)";
                 *                      end
                 *                      else if ((wvh4.flags & 0x40) > 0)  // MODE_FAST
                 *                      {
                 *                        FEncoder = FEncoder + " (fast)";
                 *                      }
                 */

                duration = (double)wvh4.total_samples * 1000.0 / sampleRate;
                if (duration > 0)
                {
                    bitrate = (sizeInfo.FileSize - tagSize) * 8 / (double)(samples * 1000.0 / (double)sampleRate);
                }

                Array.Clear(EncBuf, 0, 4096);
                EncBuf = r.ReadBytes(4096);

                for (tempo = 0; tempo < 4096; tempo++)
                {
                    if (0x65 == EncBuf[tempo])
                    {
                        if (0x02 == EncBuf[tempo + 1])
                        {
                            encoderbyte = EncBuf[tempo + 2];
                            switch (encoderbyte)
                            {
                            case 8: encoder = encoder + " (high)"; break;

                            case 0: encoder = encoder + " (normal)"; break;

                            case 2: encoder = encoder + " (fast)"; break;

                            case 6: encoder = encoder + " (very fast)"; break;
                            }
                            break;
                        }
                    }
                }
            }
            return(result);
        }
示例#15
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            ApeHeaderOld  APE_OLD  = new ApeHeaderOld();  // old header   <= 3.97
            ApeHeaderNew  APE_NEW  = new ApeHeaderNew();  // new header   >= 3.98
            ApeDescriptor APE_DESC = new ApeDescriptor(); // extra header >= 3.98

            int  BlocksPerFrame;
            bool LoadSuccess;
            bool result = false;

            this.sizeInfo = sizeInfo;
            resetData();

            // reading data from file
            LoadSuccess = false;

            readCommonHeader(source);

            if (StreamUtils.StringEqualsArr("MAC ", header.cID))
            {
                isValid = true;
                version = header.nVersion;

                versionStr = ((double)version / 1000).ToString().Substring(0, 4); //Str(FVersion / 1000 : 4 : 2, FVersionStr);

                // Load New Monkey's Audio Header for version >= 3.98
                if (header.nVersion >= 3980)
                {
                    APE_DESC.padded                 = 0;
                    APE_DESC.nDescriptorBytes       = 0;
                    APE_DESC.nHeaderBytes           = 0;
                    APE_DESC.nSeekTableBytes        = 0;
                    APE_DESC.nHeaderDataBytes       = 0;
                    APE_DESC.nAPEFrameDataBytes     = 0;
                    APE_DESC.nAPEFrameDataBytesHigh = 0;
                    APE_DESC.nTerminatingDataBytes  = 0;
                    Array.Clear(APE_DESC.cFileMD5, 0, APE_DESC.cFileMD5.Length);

                    APE_DESC.padded                 = source.ReadUInt16();
                    APE_DESC.nDescriptorBytes       = source.ReadUInt32();
                    APE_DESC.nHeaderBytes           = source.ReadUInt32();
                    APE_DESC.nSeekTableBytes        = source.ReadUInt32();
                    APE_DESC.nHeaderDataBytes       = source.ReadUInt32();
                    APE_DESC.nAPEFrameDataBytes     = source.ReadUInt32();
                    APE_DESC.nAPEFrameDataBytesHigh = source.ReadUInt32();
                    APE_DESC.nTerminatingDataBytes  = source.ReadUInt32();
                    APE_DESC.cFileMD5               = source.ReadBytes(16);

                    // seek past description header
                    if (APE_DESC.nDescriptorBytes != 52)
                    {
                        source.BaseStream.Seek(APE_DESC.nDescriptorBytes - 52, SeekOrigin.Current);
                    }
                    // load new ape_header
                    if (APE_DESC.nHeaderBytes > 24 /*sizeof(APE_NEW)*/)
                    {
                        APE_DESC.nHeaderBytes = 24 /*sizeof(APE_NEW)*/;
                    }

                    APE_NEW.nCompressionLevel = 0;
                    APE_NEW.nFormatFlags      = 0;
                    APE_NEW.nBlocksPerFrame   = 0;
                    APE_NEW.nFinalFrameBlocks = 0;
                    APE_NEW.nTotalFrames      = 0;
                    APE_NEW.nBitsPerSample    = 0;
                    APE_NEW.nChannels         = 0;
                    APE_NEW.nSampleRate       = 0;

                    APE_NEW.nCompressionLevel = source.ReadUInt16();
                    APE_NEW.nFormatFlags      = source.ReadUInt16();
                    APE_NEW.nBlocksPerFrame   = source.ReadUInt32();
                    APE_NEW.nFinalFrameBlocks = source.ReadUInt32();
                    APE_NEW.nTotalFrames      = source.ReadUInt32();
                    APE_NEW.nBitsPerSample    = source.ReadUInt16();
                    APE_NEW.nChannels         = source.ReadUInt16();
                    APE_NEW.nSampleRate       = source.ReadUInt32();

                    // based on MAC SDK 3.98a1 (APEinfo.h)
                    sampleRate          = (int)APE_NEW.nSampleRate;
                    channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(APE_NEW.nChannels);
                    formatFlags         = APE_NEW.nFormatFlags;
                    bits            = APE_NEW.nBitsPerSample;
                    compressionMode = APE_NEW.nCompressionLevel;
                    // calculate total uncompressed samples
                    if (APE_NEW.nTotalFrames > 0)
                    {
                        totalSamples = (long)(APE_NEW.nBlocksPerFrame) *
                                       (long)(APE_NEW.nTotalFrames - 1) +
                                       (long)(APE_NEW.nFinalFrameBlocks);
                    }
                    LoadSuccess = true;
                }
                else
                {
                    // Old Monkey <= 3.97

                    APE_OLD.nCompressionLevel = 0;
                    APE_OLD.nFormatFlags      = 0;
                    APE_OLD.nChannels         = 0;
                    APE_OLD.nSampleRate       = 0;
                    APE_OLD.nHeaderBytes      = 0;
                    APE_OLD.nTerminatingBytes = 0;
                    APE_OLD.nTotalFrames      = 0;
                    APE_OLD.nFinalFrameBlocks = 0;
                    APE_OLD.nInt = 0;

                    APE_OLD.nCompressionLevel = source.ReadUInt16();
                    APE_OLD.nFormatFlags      = source.ReadUInt16();
                    APE_OLD.nChannels         = source.ReadUInt16();
                    APE_OLD.nSampleRate       = source.ReadUInt32();
                    APE_OLD.nHeaderBytes      = source.ReadUInt32();
                    APE_OLD.nTerminatingBytes = source.ReadUInt32();
                    APE_OLD.nTotalFrames      = source.ReadUInt32();
                    APE_OLD.nFinalFrameBlocks = source.ReadUInt32();
                    APE_OLD.nInt = source.ReadInt32();

                    compressionMode     = APE_OLD.nCompressionLevel;
                    sampleRate          = (int)APE_OLD.nSampleRate;
                    channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(APE_OLD.nChannels);
                    formatFlags         = APE_OLD.nFormatFlags;
                    bits = 16;
                    if ((APE_OLD.nFormatFlags & MONKEY_FLAG_8_BIT) != 0)
                    {
                        bits = 8;
                    }
                    if ((APE_OLD.nFormatFlags & MONKEY_FLAG_24_BIT) != 0)
                    {
                        bits = 24;
                    }

                    hasSeekElements = ((APE_OLD.nFormatFlags & MONKEY_FLAG_PEAK_LEVEL) != 0);
                    wavNotStored    = ((APE_OLD.nFormatFlags & MONKEY_FLAG_SEEK_ELEMENTS) != 0);
                    hasPeakLevel    = ((APE_OLD.nFormatFlags & MONKEY_FLAG_WAV_NOT_STORED) != 0);

                    if (hasPeakLevel)
                    {
                        peakLevel      = (uint)APE_OLD.nInt;
                        peakLevelRatio = (peakLevel / (1 << bits) / 2.0) * 100.0;
                    }

                    // based on MAC_SDK_397 (APEinfo.cpp)
                    if (version >= 3950)
                    {
                        BlocksPerFrame = 73728 * 4;
                    }
                    else if ((version >= 3900) || ((version >= 3800) && (MONKEY_COMPRESSION_EXTRA_HIGH == APE_OLD.nCompressionLevel)))
                    {
                        BlocksPerFrame = 73728;
                    }
                    else
                    {
                        BlocksPerFrame = 9216;
                    }

                    // calculate total uncompressed samples
                    if (APE_OLD.nTotalFrames > 0)
                    {
                        totalSamples = (long)(APE_OLD.nTotalFrames - 1) *
                                       (long)(BlocksPerFrame) +
                                       (long)(APE_OLD.nFinalFrameBlocks);
                    }
                    LoadSuccess = true;
                }
                if (LoadSuccess)
                {
                    // compression profile name
                    if ((0 == (compressionMode % 1000)) && (compressionMode <= 6000))
                    {
                        compressionModeStr = MONKEY_COMPRESSION[compressionMode / 1000]; // int division
                    }
                    else
                    {
                        compressionModeStr = compressionMode.ToString();
                    }
                    // length
                    if (sampleRate > 0)
                    {
                        duration = ((double)totalSamples * 1000.0 / sampleRate);
                    }
                    // average bitrate
                    if (duration > 0)
                    {
                        bitrate = 8 * (sizeInfo.FileSize - sizeInfo.TotalTagSize) / (duration);
                    }
                    // some extra sanity checks
                    isValid = ((bits > 0) && (sampleRate > 0) && (totalSamples > 0) && (channelsArrangement.NbChannels > 0));
                    result  = isValid;
                }
            }

            return(result);
        }
示例#16
0
        private bool _ReadV3(BinaryReader r)
        {
            RiffChunk chunk = new RiffChunk();

            char[]         wavchunk;
            FormatChunk    fmt;
            bool           hasfmt;
            WavpackHeader3 wvh3   = new WavpackHeader3();
            bool           result = false;


            hasfmt = false;

            // read and evaluate header
            chunk.Reset();

            chunk.id   = r.ReadChars(4);
            chunk.size = r.ReadUInt32();
            wavchunk   = r.ReadChars(4);

            if (!StreamUtils.StringEqualsArr("WAVE", wavchunk))
            {
                return(result);
            }

            // start looking for chunks
            chunk.Reset();

            while (r.BaseStream.Position < r.BaseStream.Length)
            {
                chunk.id   = r.ReadChars(4);
                chunk.size = r.ReadUInt32();

                if (chunk.size <= 0)
                {
                    break;
                }

                if (StreamUtils.StringEqualsArr("fmt ", chunk.id))  // Format chunk found read it
                {
                    if (chunk.size >= 16 /*sizeof(fmt_chunk)*/)
                    {
                        fmt.wformattag       = r.ReadUInt16();
                        fmt.wchannels        = r.ReadUInt16();
                        fmt.dwsamplespersec  = r.ReadUInt32();
                        fmt.dwavgbytespersec = r.ReadUInt32();
                        fmt.wblockalign      = r.ReadUInt16();
                        fmt.wbitspersample   = r.ReadUInt16();

                        hasfmt              = true;
                        result              = true;
                        formatTag           = fmt.wformattag;
                        channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(fmt.wchannels);
                        sampleRate          = (int)fmt.dwsamplespersec;
                        bits    = fmt.wbitspersample;
                        bitrate = (double)fmt.dwavgbytespersec * 8;
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    if ((StreamUtils.StringEqualsArr("data", chunk.id)) && hasfmt)
                    {
                        wvh3.Reset();

                        wvh3.ckID          = r.ReadChars(4);
                        wvh3.ckSize        = r.ReadUInt32();
                        wvh3.version       = r.ReadUInt16();
                        wvh3.bits          = r.ReadUInt16();
                        wvh3.flags         = r.ReadUInt16();
                        wvh3.shift         = r.ReadUInt16();
                        wvh3.total_samples = r.ReadUInt32();
                        wvh3.crc           = r.ReadUInt32();
                        wvh3.crc2          = r.ReadUInt32();
                        wvh3.extension     = r.ReadChars(4);
                        wvh3.extra_bc      = r.ReadByte();
                        wvh3.extras        = r.ReadChars(3);

                        if (StreamUtils.StringEqualsArr("wvpk", wvh3.ckID))  // wavpack header found
                        {
                            result              = true;
                            version             = wvh3.version;
                            channelsArrangement = ChannelsArrangements.GuessFromChannelNumber(2 - (wvh3.flags & 1));
                            samples             = wvh3.total_samples;

                            codecFamily = AudioDataIOFactory.CF_LOSSLESS;

                            // Encoder guess
                            if (wvh3.bits > 0)
                            {
                                if ((wvh3.flags & NEW_HIGH_FLAG_v3) > 0)
                                {
                                    encoder = "hybrid";
                                    if ((wvh3.flags & WVC_FLAG_v3) > 0)
                                    {
                                        encoder += " lossless";
                                    }
                                    else
                                    {
                                        encoder    += " lossy";
                                        codecFamily = AudioDataIOFactory.CF_LOSSY;
                                    }

                                    if ((wvh3.flags & EXTREME_DECORR_v3) > 0)
                                    {
                                        encoder = encoder + " (high)";
                                    }
                                }
                                else
                                {
                                    if ((wvh3.flags & (HIGH_FLAG_v3 | FAST_FLAG_v3)) == 0)
                                    {
                                        encoder     = (wvh3.bits + 3).ToString() + "-bit lossy";
                                        codecFamily = AudioDataIOFactory.CF_LOSSY;
                                    }
                                    else
                                    {
                                        encoder     = (wvh3.bits + 3).ToString() + "-bit lossy";
                                        codecFamily = AudioDataIOFactory.CF_LOSSY;

                                        if ((wvh3.flags & HIGH_FLAG_v3) > 0)
                                        {
                                            encoder += " high";
                                        }
                                        else
                                        {
                                            encoder += " fast";
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if ((wvh3.flags & HIGH_FLAG_v3) == 0)
                                {
                                    encoder = "lossless (fast mode)";
                                }
                                else
                                {
                                    if ((wvh3.flags & EXTREME_DECORR_v3) > 0)
                                    {
                                        encoder = "lossless (high mode)";
                                    }
                                    else
                                    {
                                        encoder = "lossless";
                                    }
                                }
                            }

                            if (sampleRate <= 0)
                            {
                                sampleRate = 44100;
                            }
                            duration = (double)wvh3.total_samples * 1000.0 / sampleRate;
                            if (duration > 0)
                            {
                                bitrate = 8.0 * (sizeInfo.FileSize - tagSize - (double)wvh3.ckSize) / duration;
                            }
                        }
                        break;
                    }
                    else // not a wv file
                    {
                        break;
                    }
                }
            } // while

            return(result);
        }
示例#17
0
文件: AC3.cs 项目: skolmer/atldotnet
        // ---------- SUPPORT METHODS

        /* Unused for now
         * private double getCompressionRatio()
         * {
         *  // Get compression ratio
         *  if (isValid)
         *      return (double)sizeInfo.FileSize / ((duration * sampleRate) * (channels * bits / 8) + 44) * 100;
         *  else
         *      return 0;
         * }
         */

        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            ushort signatureChunk;
            byte   aByte;

            this.sizeInfo = sizeInfo;
            resetData();

            bool result = false;

            source.BaseStream.Seek(0, SeekOrigin.Begin);
            signatureChunk = source.ReadUInt16();

            if (30475 == signatureChunk)
            {
                source.BaseStream.Seek(2, SeekOrigin.Current);
                aByte = source.ReadByte();

                switch (aByte & 0xC0)
                {
                case 0: sampleRate = 48000; break;

                case 0x40: sampleRate = 44100; break;

                case 0x80: sampleRate = 32000; break;

                default: sampleRate = 0; break;
                }

                bitrate = BITRATES[(aByte & 0x3F) >> 1];

                source.BaseStream.Seek(1, SeekOrigin.Current);
                aByte = source.ReadByte();

                switch (aByte & 0xE0)
                {
                case 0: channelsArrangement = DUAL_MONO; break;

                case 0x20: channelsArrangement = MONO; break;

                case 0x40: channelsArrangement = STEREO; break;

                case 0x60: channelsArrangement = ISO_3_0_0; break;

                case 0x80: channelsArrangement = ISO_2_1_0; break;

                case 0xA0: channelsArrangement = ISO_3_1_0; break;

                case 0xC0: channelsArrangement = ISO_2_2_0; break;

                case 0xE0: channelsArrangement = ISO_3_2_0; break;

                default: channelsArrangement = UNKNOWN; break;
                }

                duration = sizeInfo.FileSize * 8.0 / bitrate;

                result = true;
            }

            return(result);
        }
示例#18
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);
        }
示例#19
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            uint   signatureChunk;
            ushort aWord;

            byte[] specDTS;
            bool   result = false;

            this.sizeInfo = sizeInfo;

            resetData();

            signatureChunk = source.ReadUInt32();
            if (/*0x7FFE8001*/ 25230975 == signatureChunk)
            {
                AudioDataOffset = source.BaseStream.Position - 4;
                AudioDataSize   = sizeInfo.FileSize - sizeInfo.APESize - sizeInfo.ID3v1Size - AudioDataOffset;

                source.BaseStream.Seek(3, SeekOrigin.Current);
                specDTS = source.ReadBytes(8);

                isValid = true;

                aWord = (ushort)(specDTS[1] | (specDTS[0] << 8));

                switch ((aWord & 0x0FC0) >> 6)
                {
                case 0: channelsArrangement = MONO; break;

                case 1: channelsArrangement = DUAL_MONO; break;

                case 2: channelsArrangement = STEREO; break;

                case 3: channelsArrangement = STEREO_SUM_DIFFERENCE; break;

                case 4: channelsArrangement = STEREO_LEFT_RIGHT_TOTAL; break;

                case 5: channelsArrangement = ISO_3_0_0; break;

                case 6: channelsArrangement = ISO_2_1_0; break;

                case 7: channelsArrangement = LRCS; break;

                case 8: channelsArrangement = QUAD; break;

                case 9: channelsArrangement = ISO_3_2_0; break;

                case 10: channelsArrangement = CLCRLRSLSR; break;

                case 11: channelsArrangement = CLRLRRRO; break;

                case 12: channelsArrangement = CFCRLFRFLRRR; break;

                case 13: channelsArrangement = CLCCRLRSLSR; break;

                case 14: channelsArrangement = CLCRLRSL1SL2SR1SR2; break;

                case 15: channelsArrangement = CLCCRLRSLSSR; break;

                default: channelsArrangement = UNKNOWN; break;
                }

                switch ((aWord & 0x3C) >> 2)
                {
                case 1: sampleRate = 8000; break;

                case 2: sampleRate = 16000; break;

                case 3: sampleRate = 32000; break;

                case 6: sampleRate = 11025; break;

                case 7: sampleRate = 22050; break;

                case 8: sampleRate = 44100; break;

                case 11: sampleRate = 12000; break;

                case 12: sampleRate = 24000; break;

                case 13: sampleRate = 48000; break;

                default: sampleRate = 0; break;
                }

                aWord   = (ushort)(specDTS[2] | (specDTS[1] << 8));
                bitrate = (ushort)BITRATES[(aWord & 0x03E0) >> 5];

                aWord = (ushort)(specDTS[7] | (specDTS[6] << 8));
                switch ((aWord & 0x01C0) >> 6)
                {
                case 0:
                case 1: bits = 16; break;

                case 2:
                case 3: bits = 20; break;

                case 4:
                case 5: bits = 24; break;

                default: bits = 16; break;
                }

                duration = sizeInfo.FileSize * 8.0 / bitrate;

                result = true;
            }

            return(result);
        }
示例#20
0
        public bool Read(BinaryReader source, ReadTagParams readTagParams)
        {
            bool result = false;

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

            byte[] aMetaDataBlockHeader;
            long   position;
            uint   blockLength;
            int    blockType;
            int    blockIndex;
            bool   isLast;
            bool   bPaddingFound = false;

            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] & 0x80)) // metadata block exists
                {
                    blockIndex = 0;
                    vorbisTag.Clear();
                    if (readTagParams.PrepareForWriting)
                    {
                        if (null == zones)
                        {
                            zones = new List <Zone>();
                        }
                        else
                        {
                            zones.Clear();
                        }
                        firstBlockPosition = source.BaseStream.Position;
                    }

                    do // read more metadata blocks if available
                    {
                        aMetaDataBlockHeader = source.ReadBytes(4);
                        isLast = ((aMetaDataBlockHeader[0] & 0x80) > 0); // last flag ( first bit == 1 )

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

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

                        if (blockType == META_VORBIS_COMMENT) // Vorbis metadata
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(ZONE_VORBISTAG, position - 4, (int)blockLength + 4, new byte[0], (byte)(isLast ? 1 : 0)));
                            }
                            vorbisTag.Read(source, readTagParams);
                        }
                        else if ((blockType == META_PADDING) && (!bPaddingFound))  // Padding block
                        {
                            padding       = blockLength;                           // if we find more skip & put them in metablock array
                            paddingLast   = ((aMetaDataBlockHeader[0] & 0x80) != 0);
                            paddingIndex  = blockIndex;
                            bPaddingFound = true;
                            source.BaseStream.Seek(padding, SeekOrigin.Current); // advance into file till next block or audio data start
                        }
                        else if (blockType == META_PICTURE)
                        {
                            if (readTagParams.PrepareForWriting)
                            {
                                zones.Add(new Zone(ZONE_PICTURE, position - 4, (int)blockLength + 4, new byte[0], (byte)(isLast ? 1 : 0)));
                            }
                            vorbisTag.ReadPicture(source.BaseStream, readTagParams);
                        }
                        // TODO : support for CUESHEET block

                        if (blockType < 7)
                        {
                            source.BaseStream.Seek(position + blockLength, SeekOrigin.Begin);
                        }
                        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.Name.Equals(ZONE_PICTURE))
                            {
                                pictureFound = true;
                            }
                            else if (zone.Name.Equals(ZONE_VORBISTAG))
                            {
                                vorbisTagFound = true;
                            }
                        }

                        if (!vorbisTagFound)
                        {
                            zones.Add(new Zone(ZONE_VORBISTAG, firstBlockPosition, 0, new byte[0]));
                        }
                        if (!pictureFound)
                        {
                            zones.Add(new Zone(ZONE_PICTURE, firstBlockPosition, 0, new byte[0]));
                        }
                    }
                }
            }

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

            return(result);
        }
示例#21
0
文件: AIFF.cs 项目: jda808/atldotnet
        protected override bool read(BinaryReader source, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = false;
            long position;

            resetData();
            source.BaseStream.Seek(0, SeekOrigin.Begin);

            if (AIFF_CONTAINER_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                // Container chunk size
                long containerChunkPos  = source.BaseStream.Position;
                int  containerChunkSize = StreamUtils.DecodeBEInt32(source.ReadBytes(4));

                if (containerChunkPos + containerChunkSize + 4 != source.BaseStream.Length)
                {
                    LogDelegator.GetLogDelegate()(Log.LV_WARNING, "Header size is incoherent with file size");
                }

                // Form type
                format = Utils.Latin1Encoding.GetString(source.ReadBytes(4));

                if (format.Equals(FORMTYPE_AIFF) || format.Equals(FORMTYPE_AIFC))
                {
                    isValid = true;

                    StringBuilder commentStr         = new StringBuilder("");
                    long          soundChunkPosition = 0;
                    long          soundChunkSize     = 0; // Header size included
                    bool          nameFound          = false;
                    bool          authorFound        = false;
                    bool          copyrightFound     = false;
                    bool          commentsFound      = false;
                    long          limit = Math.Min(containerChunkPos + containerChunkSize + 4, source.BaseStream.Length);

                    int annotationIndex = 0;
                    int commentIndex    = 0;

                    while (source.BaseStream.Position < limit)
                    {
                        ChunkHeader header = seekNextChunkHeader(source, limit);

                        position = source.BaseStream.Position;

                        if (header.ID.Equals(CHUNKTYPE_COMMON))
                        {
                            short channels = StreamUtils.DecodeBEInt16(source.ReadBytes(2));
                            switch (channels)
                            {
                            case 1: channelsArrangement = MONO; break;

                            case 2: channelsArrangement = STEREO; break;

                            case 3: channelsArrangement = ISO_3_0_0; break;

                            case 4: channelsArrangement = ISO_2_2_0; break;     // Specs actually allow both 2/2.0 and LRCS

                            case 6: channelsArrangement = LRLcRcCS; break;

                            default: channelsArrangement = UNKNOWN; break;
                            }

                            numSampleFrames = StreamUtils.DecodeBEUInt32(source.ReadBytes(4));
                            sampleSize      = (uint)StreamUtils.DecodeBEInt16(source.ReadBytes(2)); // This sample size is for uncompressed data only
                            byte[] byteArray = source.ReadBytes(10);
                            Array.Reverse(byteArray);
                            double aSampleRate = StreamUtils.ExtendedToDouble(byteArray);

                            if (format.Equals(FORMTYPE_AIFC))
                            {
                                compression = Utils.Latin1Encoding.GetString(source.ReadBytes(4));
                            }
                            else // AIFF <=> no compression
                            {
                                compression = COMPRESSION_NONE;
                            }

                            if (aSampleRate > 0)
                            {
                                sampleRate = (int)Math.Round(aSampleRate);
                                duration   = (double)numSampleFrames * 1000.0 / sampleRate;

                                if (!compression.Equals(COMPRESSION_NONE)) // Sample size is specific to selected compression method
                                {
                                    if (compression.ToLower().Equals("fl32"))
                                    {
                                        sampleSize = 32;
                                    }
                                    else if (compression.ToLower().Equals("fl64"))
                                    {
                                        sampleSize = 64;
                                    }
                                    else if (compression.ToLower().Equals("alaw"))
                                    {
                                        sampleSize = 8;
                                    }
                                    else if (compression.ToLower().Equals("ulaw"))
                                    {
                                        sampleSize = 8;
                                    }
                                }
                                if (duration > 0)
                                {
                                    bitrate = sampleSize * numSampleFrames * channelsArrangement.NbChannels / duration;
                                }
                            }
                        }
                        else if (header.ID.Equals(CHUNKTYPE_SOUND))
                        {
                            soundChunkPosition = source.BaseStream.Position - 8;
                            soundChunkSize     = header.Size + 8;
                        }
                        else if (header.ID.Equals(CHUNKTYPE_NAME) || header.ID.Equals(CHUNKTYPE_AUTHOR) || header.ID.Equals(CHUNKTYPE_COPYRIGHT))
                        {
                            structureHelper.AddZone(source.BaseStream.Position - 8, header.Size + 8, header.ID);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, header.ID);

                            tagExists = true;
                            if (header.ID.Equals(CHUNKTYPE_NAME))
                            {
                                nameFound = true;
                            }
                            if (header.ID.Equals(CHUNKTYPE_AUTHOR))
                            {
                                authorFound = true;
                            }
                            if (header.ID.Equals(CHUNKTYPE_COPYRIGHT))
                            {
                                copyrightFound = true;
                            }

                            SetMetaField(header.ID, Utils.Latin1Encoding.GetString(source.ReadBytes(header.Size)), readTagParams.ReadAllMetaFrames);
                        }
                        else if (header.ID.Equals(CHUNKTYPE_ANNOTATION))
                        {
                            annotationIndex++;
                            structureHelper.AddZone(source.BaseStream.Position - 8, header.Size + 8, header.ID + annotationIndex);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, header.ID + annotationIndex);

                            if (commentStr.Length > 0)
                            {
                                commentStr.Append(Settings.InternalValueSeparator);
                            }
                            commentStr.Append(Utils.Latin1Encoding.GetString(source.ReadBytes(header.Size)));
                            tagExists = true;
                        }
                        else if (header.ID.Equals(CHUNKTYPE_COMMENTS))
                        {
                            commentIndex++;
                            structureHelper.AddZone(source.BaseStream.Position - 8, header.Size + 8, header.ID + commentIndex);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, header.ID + commentIndex);

                            tagExists     = true;
                            commentsFound = true;

                            ushort numComs = StreamUtils.DecodeBEUInt16(source.ReadBytes(2));

                            for (int i = 0; i < numComs; i++)
                            {
                                CommentData cmtData = new CommentData();
                                cmtData.Timestamp = StreamUtils.DecodeBEUInt32(source.ReadBytes(4));
                                cmtData.MarkerId  = StreamUtils.DecodeBEInt16(source.ReadBytes(2));

                                // Comments length
                                ushort        comLength = StreamUtils.DecodeBEUInt16(source.ReadBytes(2));
                                MetaFieldInfo comment   = new MetaFieldInfo(getImplementedTagType(), header.ID + commentIndex);
                                comment.Value        = Utils.Latin1Encoding.GetString(source.ReadBytes(comLength));
                                comment.SpecificData = cmtData;
                                tagData.AdditionalFields.Add(comment);

                                // Only read general purpose comments, not those linked to a marker
                                if (0 == cmtData.MarkerId)
                                {
                                    if (commentStr.Length > 0)
                                    {
                                        commentStr.Append(Settings.InternalValueSeparator);
                                    }
                                    commentStr.Append(comment.Value);
                                }
                            }
                        }
                        else if (header.ID.Equals(CHUNKTYPE_ID3TAG))
                        {
                            id3v2Offset = source.BaseStream.Position;

                            // Zone is already added by Id3v2.Read
                            id3v2StructureHelper.AddZone(id3v2Offset - 8, header.Size + 8, CHUNKTYPE_ID3TAG);
                            id3v2StructureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_ID3TAG);
                        }

                        source.BaseStream.Position = position + header.Size;

                        if (header.ID.Equals(CHUNKTYPE_SOUND) && header.Size % 2 > 0)
                        {
                            source.BaseStream.Position += 1;                                                           // Sound chunk size must be even
                        }
                    }

                    tagData.IntegrateValue(TagData.TAG_FIELD_COMMENT, commentStr.ToString().Replace("\0", " ").Trim());

                    if (-1 == id3v2Offset)
                    {
                        id3v2Offset = 0; // Switch status to "tried to read, but nothing found"

                        if (readTagParams.PrepareForWriting)
                        {
                            id3v2StructureHelper.AddZone(soundChunkPosition + soundChunkSize, 0, CHUNKTYPE_ID3TAG);
                            id3v2StructureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_ID3TAG);
                        }
                    }

                    // Add zone placeholders for future tag writing
                    if (readTagParams.PrepareForWriting)
                    {
                        if (!nameFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_NAME);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_NAME);
                        }
                        if (!authorFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_AUTHOR);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_AUTHOR);
                        }
                        if (!copyrightFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_COPYRIGHT);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_COPYRIGHT);
                        }
                        if (!commentsFound)
                        {
                            structureHelper.AddZone(soundChunkPosition, 0, CHUNKTYPE_COMMENTS);
                            structureHelper.AddSize(containerChunkPos, containerChunkSize, CHUNKTYPE_COMMENTS);
                        }
                    }

                    result = true;
                }
            }

            return(result);
        }
示例#22
0
        public bool Read(BinaryReader source, SizeInfo sizeInfo, MetaDataIO.ReadTagParams readTagParams)
        {
            bool result = false;
            bool doLoop = true;
            long position;

            UInt16 readData16;
            UInt32 readData32;

            UInt32 metaType;
            UInt32 metaSize;
            long   sampleCount   = 0;
            int    frameSizeType = -1;

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

            if (TAK_ID.Equals(Utils.Latin1Encoding.GetString(source.ReadBytes(4))))
            {
                result   = true;
                position = source.BaseStream.Position;

                source.BaseStream.Seek(position, SeekOrigin.Begin);

                do // Loop metadata
                {
                    readData32 = source.ReadUInt32();

                    metaType = readData32 & 0x7F;
                    metaSize = readData32 >> 8;

                    position = source.BaseStream.Position;

                    if (0 == metaType)
                    {
                        doLoop = false;        // End of metadata
                    }
                    else if (0x01 == metaType) // Stream info
                    {
                        readData16    = source.ReadUInt16();
                        frameSizeType = readData16 & 0x003C; // bits 11 to 14
                        readData32    = source.ReadUInt32();
                        uint restOfData = source.ReadUInt32();

                        sampleCount = (readData16 >> 14) + (readData32 << 2) + ((restOfData & 0x00000080) << 34);

                        sampleRate          = ((restOfData >> 4) & 0x03ffff) + 6000;                                             // bits 4 to 21
                        channelsArrangement = ChannelsArrangements.GuessFromChannelNumber((int)((restOfData >> 27) & 0x0F) + 1); // bits 28 to 31

                        if (sampleCount > 0)
                        {
                            duration = (double)sampleCount * 1000.0 / sampleRate;
                            bitrate  = Math.Round(((double)(sizeInfo.FileSize - source.BaseStream.Position)) * 8 / duration); //time to calculate average bitrate
                        }
                    }
                    else if (0x04 == metaType) // Encoder info
                    {
                        readData32     = source.ReadUInt32();
                        formatVersion  = 100 * ((readData32 & 0x00ff0000) >> 16);
                        formatVersion += 10 * ((readData32 & 0x0000ff00) >> 8);
                        formatVersion += (readData32 & 0x000000ff);
                    }

                    source.BaseStream.Seek(position + metaSize, SeekOrigin.Begin);
                } while (doLoop); // End of metadata loop
            }

            return(result);
        }