예제 #1
0
        /// <summary>
        /// Reads all <see cref="FlacMetadata"/> from the specified <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The stream which contains the <see cref="FlacMetadata"/>.</param>
        /// <returns>All <see cref="FlacMetadata"/>.</returns>
        public static IEnumerable <FlacMetadata> ReadAllMetadataFromStream(Stream stream)
        {
            while (true)
            {
                FlacMetadata data = FromStream(stream);
                yield return(data);

                if (data == null || data.IsLastMetaBlock)
                {
                    break;
                }
            }
        }
예제 #2
0
        public unsafe static FlacMetadata FromStream(Stream stream)
        {
            bool             lastBlock = false;
            FlacMetaDataType type      = FlacMetaDataType.Undef;
            int length = 0;

            byte[] b = new byte[4];
            if (stream.Read(b, 0, 4) <= 0)
            {
                throw new FlacException(new EndOfStreamException("Could not read metadata"), FlacLayer.Metadata);

                fixed(byte *headerBytes = b)
                {
                    FlacBitReader bitReader = new FlacBitReader(headerBytes, 0);

                    lastBlock = bitReader.ReadBits(1) == 1;
                    type      = (FlacMetaDataType)bitReader.ReadBits(7);
                    length    = (int)bitReader.ReadBits(24);
                    ////1000 0000
                    //if (((b[0] & 0x80) >> 7) == 1)
                    //    lastBlock = true;
                    //type = (FlacMetaDataType)(b[0] & 0x7F);
                    //int length = (b[1] + (b[2] << 8) + (b[3] << 16));
                }

                FlacMetadata data;
                long streamStartPosition = stream.Position;
                if ((int)type < 0 || (int)type > 6)
                    return(null); }
                else
                {
                    switch (type)
                    {
                    case FlacMetaDataType.StreamInfo:
                        data = new FlacMetadataStreamInfo(stream, length, lastBlock);
                        break;

                    case FlacMetaDataType.Seektable:
                        data = new FlacMetadataSeekTable(stream, length, lastBlock);
                        break;

                    default:
                        data = new FlacMetadata(type, lastBlock, length);
                        break;
                    }
                }

                stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current);
                return(data);
        }
예제 #3
0
        private unsafe List<FlacFrameInformation> ScanThisShit(FlacMetadataStreamInfo streamInfo)
        {
            Stream stream = _stream;

            //if (!(stream is BufferedStream))
            //    stream = new BufferedStream(stream);

            byte[] buffer = new byte[BufferSize];
            stream.Position = 4; //fLaC

            //skip the metadata
            FlacMetadata.SkipMetadata(stream);

            List<FlacFrameInformation> frames = new List<FlacFrameInformation>();
            FlacFrameInformation frameInfo = new FlacFrameInformation();
            frameInfo.IsFirstFrame = true;

            FlacFrameHeader baseHeader = null;

            while (true)
            {
                int read = stream.Read(buffer, 0, buffer.Length);
                if (read <= FlacConstant.FrameHeaderSize)
                    break;

                fixed (byte* bufferPtr = buffer)
                {
                    byte* ptr = bufferPtr;
                    //for (int i = 0; i < read - FlacConstant.FrameHeaderSize; i++)
                    while ((bufferPtr + read - FlacConstant.FrameHeaderSize) > ptr)
                    {
                        if (*ptr++ == 0xFF && (*ptr & 0xF8) == 0xF8) //check sync
                        {
                            byte* ptrSafe = ptr;
                            ptr--;
                            FlacFrameHeader tmp;
                            if (IsFrame(ref ptr, streamInfo, out tmp))
                            {
                                FlacFrameHeader header = tmp;
                                if (frameInfo.IsFirstFrame)
                                {
                                    baseHeader = header;
                                    frameInfo.IsFirstFrame = false;
                                }

                                if (baseHeader != null && baseHeader.IsFormatEqualTo(header))
                                {
                                    frameInfo.StreamOffset = stream.Position - read + ((ptrSafe - 1) - bufferPtr);
                                    frameInfo.Header = header;
                                    frames.Add(frameInfo);

                                    frameInfo.SampleOffset += header.BlockSize;
                                }
                                else
                                {
                                    ptr = ptrSafe;
                                }
                            }
                            else
                            {
                                ptr = ptrSafe;
                            }
                        }
                    }
                }

                stream.Position -= FlacConstant.FrameHeaderSize;
            }

            return frames;
        }
예제 #4
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="FlacFile" /> class.
        /// </summary>
        /// <param name="stream">Stream which contains flac data which should be decoded.</param>
        /// <param name="scanFlag">Scan mode which defines how to scan the flac data for frames.</param>
        /// <param name="onscanFinished">
        ///     Callback which gets called when the pre scan processes finished. Should be used if the
        ///     <paramref name="scanFlag" /> argument is set the <see cref="FlacPreScanMode.Async" />.
        /// </param>
        public FlacFile(Stream stream, FlacPreScanMode scanFlag,
                        Action <FlacPreScanFinishedEventArgs> onscanFinished)
        {
            if (stream == null)
            {
                throw new ArgumentNullException();
            }
            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream is not readable.", "stream");
            }

            _stream      = stream;
            _closeStream = true;

            //skip ID3v2
            while (ID3v2.SkipTag(stream))
            {
            }

            //read fLaC sync
            var beginSync = new byte[4];
            int read      = stream.Read(beginSync, 0, beginSync.Length);

            if (read < beginSync.Length)
            {
                throw new EndOfStreamException("Can not read \"fLaC\" sync.");
            }
            if (beginSync[0] == 0x66 && beginSync[1] == 0x4C && //Check for 'fLaC' signature
                beginSync[2] == 0x61 && beginSync[3] == 0x43)
            {
                //read metadata
                List <FlacMetadata> metadata = FlacMetadata.ReadAllMetadataFromStream(stream).ToList();

                Metadata = metadata.AsReadOnly();
                if (metadata.Count <= 0)
                {
                    throw new FlacException("No Metadata found.", FlacLayer.Metadata);
                }

                var streamInfo =
                    metadata.First(x => x.MetaDataType == FlacMetaDataType.StreamInfo) as FlacMetadataStreamInfo;
                if (streamInfo == null)
                {
                    throw new FlacException("No StreamInfo-Metadata found.", FlacLayer.Metadata);
                }

                _streamInfo = streamInfo;
                _waveFormat = CreateWaveFormat(streamInfo);
                Log.Verbose("Flac StreamInfo found -> WaveFormat: " + _waveFormat);
                Log.Verbose("Flac-File-Metadata read.");
            }
            else
            {
                throw new FlacException("Invalid Flac-File. \"fLaC\" Sync not found.", FlacLayer.OutSideOfFrame);
            }

            //prescan stream
            if (scanFlag != FlacPreScanMode.None)
            {
                var scan = new FlacPreScan(stream);
                scan.ScanFinished += (s, e) =>
                {
                    onscanFinished?.Invoke(e);
                };
                scan.ScanStream(_streamInfo, scanFlag);
                _scan = scan;
            }
        }
예제 #5
0
파일: FlacFile.cs 프로젝트: yazici/AudioLab
        public FlacFile(Stream stream, FlacPreScanMethodMode?scanFlag, Action <FlacPreScanFinishedEventArgs> onscanFinished)
        {
            if (stream == null)
            {
                throw new ArgumentNullException();
            }
            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream is not readable.", "stream");
            }

            _stream = stream;

            //skip ID3v2
            Tags.ID3.ID3v2.SkipTag(stream);
            int read = 0;

            //read fLaC sync
            byte[] beginSync = new byte[4];
            read = stream.Read(beginSync, 0, beginSync.Length);
            if (read < beginSync.Length)
            {
                throw new EndOfStreamException("Can not read \"fLaC\" sync.");
            }
            if (beginSync[0] == 0x66 && beginSync[1] == 0x4C &&
                beginSync[2] == 0x61 && beginSync[3] == 0x43)
            {
                //read metadata
                var metadata = FlacMetadata.AllDataFromStream(stream);

                Metadata = metadata;
                if (metadata == null || metadata.Count <= 0)
                {
                    throw new FlacException("No Metadata found.", FlacLayer.Metadata);
                }

                FlacMetadataStreamInfo streamInfo = metadata.Where(x => x.MetaDataType == FlacMetaDataType.StreamInfo).First() as FlacMetadataStreamInfo;
                if (streamInfo == null)
                {
                    new FlacException("No StreamInfo-Metadata found.", FlacLayer.Metadata);
                }

                _streamInfo = streamInfo;
                _waveFormat = new WaveFormat(streamInfo.SampleRate, (short)streamInfo.BitsPerSample, (short)streamInfo.Channels, AudioEncoding.Pcm);
                Debug.WriteLine("Flac StreamInfo found -> WaveFormat: " + _waveFormat.ToString());
                Debug.WriteLine("Flac-File-Metadata read.");
            }
            else
            {
                throw new FlacException("Invalid Flac-File. \"fLaC\" Sync not found.", FlacLayer.Top);
            }

            //prescan stream
            if (scanFlag != null)
            {
                FlacPreScan scan = new FlacPreScan(stream);
                scan.ScanFinished += (s, e) =>
                {
                    if (onscanFinished != null)
                    {
                        onscanFinished(e);
                    }
                };
                scan.ScanStream(_streamInfo, (FlacPreScanMethodMode)scanFlag);
                _scan = scan;
            }
        }
예제 #6
0
        public static unsafe FlacMetadata FromStream(Stream stream)
        {
            bool lastBlock = false;
            FlacMetaDataType type = FlacMetaDataType.Undef;
            int length = 0;

            byte[] b = new byte[4];
            if (stream.Read(b, 0, 4) <= 0)
                throw new FlacException(new EndOfStreamException("Could not read metadata"), FlacLayer.Metadata);

            fixed (byte* headerBytes = b)
            {
                FlacBitReader bitReader = new FlacBitReader(headerBytes, 0);

                lastBlock = bitReader.ReadBits(1) == 1;
                type = (FlacMetaDataType)bitReader.ReadBits(7);
                length = (int)bitReader.ReadBits(24);
                ////1000 0000
                //if (((b[0] & 0x80) >> 7) == 1)
                //    lastBlock = true;
                //type = (FlacMetaDataType)(b[0] & 0x7F);
                //int length = (b[1] + (b[2] << 8) + (b[3] << 16));
            }

            FlacMetadata data;
            long streamStartPosition = stream.Position;
            if ((int)type < 0 || (int)type > 6)
                return null;
            else
            {
                switch (type)
                {
                    case FlacMetaDataType.StreamInfo:
                        data = new FlacMetadataStreamInfo(stream, length, lastBlock);
                        break;

                    case FlacMetaDataType.Seektable:
                        data = new FlacMetadataSeekTable(stream, length, lastBlock);
                        break;

                    default:
                        data = new FlacMetadata(type, lastBlock, length);
                        break;
                }
            }

            stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current);
            return data;
        }
예제 #7
0
        /// <summary>
        /// Reads and returns a single <see cref="FlacMetadata"/> from the specified <paramref name="stream"/>.
        /// </summary>
        /// <param name="stream">The stream which contains the <see cref="FlacMetadata"/>.</param>
        /// <returns>Returns the read <see cref="FlacMetadata"/>.</returns>
        public static unsafe FlacMetadata FromStream(Stream stream)
        {
            bool lastBlock;
            FlacMetaDataType type;
            int length;

            byte[] b = new byte[4];
            if (stream.Read(b, 0, 4) <= 0)
                throw new FlacException(new EndOfStreamException("Could not read metadata"), FlacLayer.Metadata);

            fixed (byte* headerBytes = b)
            {
                FlacBitReader bitReader = new FlacBitReader(headerBytes, 0);

                lastBlock = bitReader.ReadBits(1) == 1;
                type = (FlacMetaDataType)bitReader.ReadBits(7);
                length = (int)bitReader.ReadBits(24);
            }

            FlacMetadata data;
            long streamStartPosition = stream.Position;
            if ((int)type < 0 || (int)type > 6)
                return null;

            switch (type)
            {
                case FlacMetaDataType.StreamInfo:
                    data = new FlacMetadataStreamInfo(stream, length, lastBlock);
                    break;

                case FlacMetaDataType.Seektable:
                    data = new FlacMetadataSeekTable(stream, length, lastBlock);
                    break;

                default:
                    data = new FlacMetadata(type, lastBlock, length);
                    break;
            }

            stream.Seek(length - (stream.Position - streamStartPosition), SeekOrigin.Current);
            return data;
        }