Beispiel #1
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);
        }
Beispiel #2
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);
        }
Beispiel #3
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);
        }
Beispiel #4
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);
        }
Beispiel #5
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);
        }
Beispiel #6
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);
        }
Beispiel #7
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);
        }
Beispiel #8
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);
        }
Beispiel #9
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);
        }