예제 #1
0
        private FlacFrame(Stream stream, FlacMetadataStreamInfo streamInfo)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (stream.CanRead == false) throw new ArgumentException("Stream is not readable");

            _stream = stream;
            _streamInfo = streamInfo;
        }
예제 #2
0
        internal unsafe FlacFrameHeader(ref byte* buffer, FlacMetadataStreamInfo streamInfo, bool doCrc, bool logError)
        {
            printErrors = logError; //optimized for prescan

            DoCRC = doCrc;
            StreamPosition = -1;

            HasError = !ParseHeader(ref buffer, streamInfo);
        }
예제 #3
0
        /// <param name="streamInfo">Can be null</param>
        public FlacFrameHeader(Stream stream, FlacMetadataStreamInfo streamInfo, bool doCrc)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (stream.CanRead == false) throw new ArgumentException("stream is not readable");
            //streamInfo can be null

            DoCRC = doCrc;
            StreamPosition = stream.Position;

            HasError = !ParseHeader(stream, streamInfo);
        }
예제 #4
0
파일: FlacPreScan.cs 프로젝트: opcon/cscore
        public void ScanStream(FlacMetadataStreamInfo streamInfo, FlacPreScanMode mode)
        {
            long saveOffset = _stream.Position;
            StartScan(streamInfo, mode);
            _stream.Position = saveOffset;

            long totalLength = 0, totalsamples = 0;
            foreach (var frame in Frames)
            {
                totalLength += frame.Header.BlockSize * frame.Header.BitsPerSample * frame.Header.Channels;
                totalsamples += frame.Header.BlockSize;
            }
            TotalLength = totalLength;
            TotalSamples = totalsamples;

            Debug.WriteLineIf(TotalSamples == streamInfo.TotalSamples, "Flac prescan successful. Calculated total_samples value matching the streaminfo-metadata.");
        }
예제 #5
0
        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
 /// <summary>
 /// Initializes a new instance of the <see cref="FlacFrameHeader"/> class.
 /// </summary>
 /// <param name="buffer">The raw byte-data which contains the <see cref="FlacFrameHeader"/>.</param>
 /// <param name="streamInfo">The stream-info-metadata-block of the flac stream which provides some basic information about the flac framestream. Can be set to null.</param>
 /// <param name="doCrc">A value which indicates whether the crc8 checksum of the <see cref="FlacFrameHeader"/> should be calculated.</param>
 public unsafe FlacFrameHeader(ref byte *buffer, FlacMetadataStreamInfo streamInfo, bool doCrc)
     : this(ref buffer, streamInfo, doCrc, true)
 {
 }
예제 #7
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);
                Debug.WriteLine("Flac StreamInfo found -> WaveFormat: " + _waveFormat);
                Debug.WriteLine("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) =>
                {
                    if (onscanFinished != null)
                    {
                        onscanFinished(e);
                    }
                };
                scan.ScanStream(_streamInfo, scanFlag);
                _scan = scan;
            }
        }
예제 #8
0
 private WaveFormat CreateWaveFormat(FlacMetadataStreamInfo streamInfo)
 {
     if (streamInfo.Channels > 2 && streamInfo.Channels <= 8)
     {
         ChannelMask channelMask;
         switch (streamInfo.Channels)
         {
             case 3:
                 //2.1
                 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight |
                               ChannelMask.SpeakerFrontCenter;
                 break;
             case 4:
                 //quadraphonic
                 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight |
                               ChannelMask.SpeakerBackLeft | ChannelMask.SpeakerBackRight;
                 break;
             case 5:
                 //5.0
                 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight |
                               ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerSideLeft |
                               ChannelMask.SpeakerSideRight;
                 break;
             case 6:
                 //5.1
                 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight |
                               ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerLowFrequency |
                               ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight;
                 break;
             case 7:
                 //6.1
                 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight |
                               ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerLowFrequency |
                               ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight |
                               ChannelMask.SpeakerBackCenter;
                 break;
             case 8:
                 //7.1
                 channelMask = ChannelMask.SpeakerFrontLeft | ChannelMask.SpeakerFrontRight |
                               ChannelMask.SpeakerFrontCenter | ChannelMask.SpeakerLowFrequency |
                               ChannelMask.SpeakerBackLeft | ChannelMask.SpeakerBackRight |
                               ChannelMask.SpeakerSideLeft | ChannelMask.SpeakerSideRight;
                 break;
             default:
                 throw new Exception("Invalid number of channels. This error should not occur.");
         }
         return new WaveFormatExtensible(streamInfo.SampleRate, streamInfo.BitsPerSample, streamInfo.Channels,
             AudioSubTypes.Pcm, channelMask);
     }
     return new WaveFormat(streamInfo.SampleRate, streamInfo.BitsPerSample, streamInfo.Channels, AudioEncoding.Pcm);
 }
예제 #9
0
 private unsafe bool IsFrame(ref byte* buffer, FlacMetadataStreamInfo streamInfo, FlacFrameHeader baseHeader, out FlacFrameHeader header)
 {
     header = new FlacFrameHeader(ref buffer, streamInfo, true, false);
     return !header.HasError;
 }
예제 #10
0
        protected virtual List<FlacFrameInformation> RunScan(FlacMetadataStreamInfo streamInfo)
        {
            #if DEBUG
            Stopwatch watch = new Stopwatch();
            watch.Start();
            #endif
            var result = ScanThisShit(streamInfo);

            #if DEBUG
            watch.Stop();
            Debug.WriteLine(String.Format("FlacPreScan finished: {0} Bytes processed in {1} ms.",
                _stream.Length.ToString(), watch.ElapsedMilliseconds.ToString()));
            #endif
            RaiseScanFinished(result);
            return result;
        }
예제 #11
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;
        }
예제 #12
0
        private unsafe bool ParseHeader(ref byte* headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";
            int val;
            if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits
            {
                if ((headerBuffer[1] & 0x02) != 0)
                {
                    Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation);
                    return false;
                }

                byte* __headerbufferPtr = headerBuffer;
                FlacBitReader reader = new FlacBitReader(__headerbufferPtr, 0);

                #region blocksize

                //blocksize
                val = headerBuffer[2] >> 4;
                int blocksize = -1;

                if (val == 0)
                {
                    Error("Invalid Blocksize value: 0", loggerLocation);
                    return false;
                }
                if (val == 1)
                    blocksize = 192;
                else if (val >= 2 && val <= 5)
                    blocksize = 576 << (val - 2);
                else if (val == 6 || val == 7)
                    _blocksizeHint = val;
                else if (val >= 8 && val <= 15)
                    blocksize = 256 << (val - 8);
                else
                {
                    Error("Invalid Blocksize value: " + val, loggerLocation);
                    return false;
                }
                BlockSize = blocksize;

                #endregion blocksize

                #region samplerate

                //samplerate
                val = headerBuffer[2] & 0x0F;
                int sampleRate = -1;

                if (val == 0)
                {
                    if (streamInfo != null)
                        sampleRate = streamInfo.SampleRate;
                    else
                    {
                        Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return false;
                    }
                }
                else if (val >= 1 && val <= 11)
                    sampleRate = FlacConstant.SampleRateTable[val];
                else if (val >= 12 && val <= 14)
                    _sampleRateHint = val;
                else
                {
                    Error("Invalid SampleRate value: " + val, loggerLocation);
                    return false;
                }
                SampleRate = sampleRate;

                #endregion samplerate

                #region channels

                val = headerBuffer[3] >> 4; //cc: unsigned
                int channels;
                if ((val & 8) != 0)
                {
                    channels = 2;
                    if ((val & 7) > 2 || (val & 7) < 0)
                    {
                        Error("Invalid ChannelAssignment", loggerLocation);
                        return false;
                    }
                    ChannelAssignment = (ChannelAssignment)((val & 7) + 1);
                }
                else
                {
                    channels = val + 1;
                    ChannelAssignment = ChannelAssignment.Independent;
                }
                Channels = channels;

                #endregion channels

                #region bitspersample

                val = (headerBuffer[3] & 0x0E) >> 1;
                int bitsPerSample;
                if (val == 0)
                {
                    if (streamInfo != null)
                        bitsPerSample = streamInfo.BitsPerSample;
                    else
                    {
                        Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return false;
                    }
                }
                else if (val == 3 || val >= 7 || val < 0)
                {
                    Error("Invalid BitsPerSampleIndex", loggerLocation);
                    return false;
                }
                else
                    bitsPerSample = FlacConstant.BitPerSampleTable[val];

                BitsPerSample = bitsPerSample;

                #endregion bitspersample

                if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0
                {
                    Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation);
                    return false;
                }

                reader.ReadBits(32); //skip the first 4 bytes since they got already processed

                //BYTE 4

                #region utf8

                //variable blocksize
                if ((headerBuffer[1] & 0x01) != 0 ||
                    (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize))
                {
                    ulong samplenumber;
                    if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.VariableBlockSize;
                        SampleNumber = (long) samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return false;
                    }
                }
                else //fixed blocksize
                {
                    uint framenumber;

                    if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.FixedBlockSize;
                        FrameNumber = (int) framenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Framenumber coding.", loggerLocation);
                        return false;
                    }
                }

                #endregion utf8

                #region read hints

                //blocksize am ende des frameheaders
                if (_blocksizeHint != 0)
                {
                    val = (int)reader.ReadBits(8);
                    if (_blocksizeHint == 7)
                    {
                        val = (val << 8) | (int)reader.ReadBits(8);
                    }
                    BlockSize = val + 1;
                }

                //samplerate
                if (_sampleRateHint != 0)
                {
                    val = (int)reader.ReadBits(8);
                    if (_sampleRateHint != 12)
                    {
                        val = (val << 8) | (int)reader.ReadBits(8);
                    }
                    if (_sampleRateHint == 12)
                        SampleRate = val * 1000;
                    else if (_sampleRateHint == 13)
                        SampleRate = val;
                    else
                        SampleRate = val * 10;
                }

                #endregion read hints

                if (DoCrc)
                {
                    var crc8 = Utils.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position);
                    Crc8 = (byte) reader.ReadBits(8);
                    if (Crc8 != crc8)
                    {
                        Error("CRC8 missmatch", loggerLocation);
                        return false;
                    }
                }
                else
                {
                    Crc8 = (byte) reader.ReadBits(8);
                }

                headerBuffer += reader.Position;
                return true;
            }

            Error("Invalid Syncbits", loggerLocation);
            return false;
        }
예제 #13
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;
        }
예제 #14
0
파일: FlacPreScan.cs 프로젝트: opcon/cscore
        private void StartScan(FlacMetadataStreamInfo streamInfo, FlacPreScanMode mode)
        {
            if (_isRunning)
                throw new Exception("Scan is already running.");

            _isRunning = true;

            if (mode == FlacPreScanMode.Async)
            {
                ThreadPool.QueueUserWorkItem(o =>
                {
                    Frames = RunScan(streamInfo);
                    _isRunning = false;
                });
            }
            else
            {
                Frames = RunScan(streamInfo);
                _isRunning = false;
            }
        }
예제 #15
0
 private unsafe bool IsFrame(ref byte *buffer, FlacMetadataStreamInfo streamInfo, out FlacFrameHeader header)
 {
     header = new FlacFrameHeader(ref buffer, streamInfo, true, false);
     return(!header.HasError);
 }
예제 #16
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);
        }
예제 #17
0
 private void Decode(Stream stream, FlacMetadataStreamInfo streamInfo)
 {
     Header = new FlacFrameHeader(stream, streamInfo);
     _stream = stream;
     _streamInfo = streamInfo;
     HasError = Header.HasError;
     if (!HasError)
     {
         ReadSubFrames();
         FreeBuffers();
     }
 }
예제 #18
0
        protected unsafe virtual bool ParseHeader(Stream stream, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(Stream, FlacMetadataStreamInfo)";

            byte[] headerBuffer = new byte[FlacConstant.FrameHeaderSize];
            if (stream.Read(headerBuffer, 0, headerBuffer.Length) == headerBuffer.Length)
            {
                fixed (byte* ptrBuffer = headerBuffer)
                {
                    byte* ptrSave = ptrBuffer;
                    byte* __ptrBuffer = ptrBuffer;
                    bool result = ParseHeader(ref __ptrBuffer, streamInfo);
                    stream.Position -= (headerBuffer.Length - (__ptrBuffer - ptrSave)); //todo

                    return result;
                }
            }
            else
            {
                Error("Not able to read Flac header - EOF?", loggerLocation);
                return false;
            }
        }
예제 #19
0
 /// <summary>
 /// Creates a new instance of the <see cref="FlacFrame"/> class based on the specified <paramref name="stream"/> and some basic stream information.
 /// </summary>
 /// <param name="stream">The stream which contains the flac frame.</param>
 /// <param name="streamInfo">Some basic information about the flac stream.</param>
 /// <returns>A new instance of the <see cref="FlacFrame"/> class.</returns>
 public static FlacFrame FromStream(Stream stream, FlacMetadataStreamInfo streamInfo)
 {
     FlacFrame frame = new FlacFrame(stream, streamInfo);
     return frame;
     //return frame.HasError ? null : frame;
 }
예제 #20
0
        protected unsafe virtual bool ParseHeader(ref byte* headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";
            int x = -1; //tmp value to store in
            if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits
            {
                if ((headerBuffer[1] & 0x02) != 0) // ...10 2. letzes bits muss 0 sein
                {
                    Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation);
                    return false;
                }

                byte* __headerbufferPtr = headerBuffer;
                FlacBitReader reader = new FlacBitReader(__headerbufferPtr, 0);

                #region blocksize

                //blocksize
                x = headerBuffer[2] >> 4;
                int blocksize = -1;

                if (x == 0)
                {
                    Error("Invalid Blocksize value: 0", loggerLocation);
                    return false;
                }
                else if (x == 1)
                    blocksize = 192;
                else if (x >= 2 && x <= 5)
                    blocksize = 576 << (x - 2);
                else if (x == 6 || x == 7)
                    blocksize_hint = x;
                else if (x >= 8 && x <= 15)
                    blocksize = 256 << (x - 8);
                else
                {
                    Error("Invalid Blocksize value: " + x, loggerLocation);
                    return false;
                }
                BlockSize = blocksize;

                #endregion blocksize

                #region samplerate

                //samplerate
                x = headerBuffer[2] & 0x0F;
                int sampleRate = -1;

                if (x == 0)
                {
                    if (streamInfo != null)
                        sampleRate = streamInfo.SampleRate;
                    else
                    {
                        Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return false;
                    }
                }
                else if (x >= 1 && x <= 11)
                    sampleRate = FlacConstant.SampleRateTable[x];
                else if (x >= 12 && x <= 14)
                    sampleRate_hint = x;
                else
                {
                    Error("Invalid SampleRate value: " + x, loggerLocation);
                    return false;
                }
                SampleRate = sampleRate;

                #endregion samplerate

                #region channels

                x = headerBuffer[3] >> 4; //cc: unsigned
                int channels = -1;
                if ((x & 8) != 0)
                {
                    channels = 2;
                    if ((x & 7) > 2 || (x & 7) < 0)
                    {
                        Error("Invalid ChannelAssignment", loggerLocation);
                        return false;
                    }
                    else
                        ChannelAssignment = (ChannelAssignment)((x & 7) + 1);
                }
                else
                {
                    channels = x + 1;
                    ChannelAssignment = ChannelAssignment.Independent;
                }
                Channels = channels;

                #endregion channels

                #region bitspersample

                x = (headerBuffer[3] & 0x0E) >> 1;
                int bitsPerSample = -1;
                if (x == 0)
                {
                    if (streamInfo != null)
                        bitsPerSample = streamInfo.BitsPerSample;
                    else
                    {
                        Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return false;
                    }
                }
                else if (x == 3 || x >= 7 || x < 0)
                {
                    Error("Invalid BitsPerSampleIndex", loggerLocation);
                    return false;
                }
                else
                    bitsPerSample = FlacConstant.BitPerSampleTable[x];

                BitsPerSample = bitsPerSample;

                #endregion bitspersample

                if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0
                {
                    Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation);
                    return false;
                }

                //reader.SkipBits(4 * 8); //erste 3 bytes headerbytes überspringen, da diese schon ohne reader verarbeitet
                reader.ReadBits(32);

                //BYTE 4

                #region utf8

                //variable blocksize
                if ((headerBuffer[1] & 0x01) != 0 ||
                    (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize))
                {
                    ulong samplenumber;
                    if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue)
                    {
                        NumberType = FlacNumberType.SampleNumber;
                        SampleNumber = samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return false;
                    }
                }
                else //fixed blocksize
                {
                    uint framenumber;// = reader.ReadUTF8();

                    if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue)
                    {
                        NumberType = FlacNumberType.FrameNumber;
                        FrameNumber = framenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Framenumber coding.", loggerLocation);
                        return false;
                    }
                }

                #endregion utf8

                #region read hints

                //blocksize am ende des frameheaders
                if (blocksize_hint != 0)
                {
                    x = (int)reader.ReadBits(8);
                    if (blocksize_hint == 7)
                    {
                        x = (x << 8) | (int)reader.ReadBits(8);
                    }
                    BlockSize = x + 1;
                }

                //samplerate am ende des frameheaders
                if (sampleRate_hint != 0)
                {
                    x = (int)reader.ReadBits(8);
                    if (sampleRate_hint != 12)
                    {
                        x = (x << 8) | (int)reader.ReadBits(8);
                    }
                    if (sampleRate_hint == 12)
                        SampleRate = x * 1000;
                    else if (sampleRate_hint == 13)
                        SampleRate = x;
                    else
                        SampleRate = x * 10;
                }

                #endregion read hints

                //if (Channels == 1 && BitsPerSample == 24 && SampleRate == 44100)
                //    System.Diagnostics.Debugger.Break();

                if (DoCRC)
                {
                    var crc8 = CSMath.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position);
                    CRC8 = (byte)reader.ReadBits(8);
                    if (CRC8 != crc8)
                    {
                        Error("CRC8 missmatch", loggerLocation);
                        return false;
                    }
                }

                headerBuffer += reader.Position;
                return true;
            }

            Error("Invalid Syncbits", loggerLocation);
            return false;
        }
예제 #21
0
        public void ScanStream(FlacMetadataStreamInfo streamInfo, FlacPreScanMethodMode method)
        {
            long saveOffset = _stream.Position;
            StartScan(streamInfo, method);
            _stream.Position = saveOffset;

            long totalLength = 0, totalsamples = 0;
            foreach (var frame in Frames)
            {
                totalLength += frame.Header.BlockSize * frame.Header.BitsPerSample * frame.Header.Channels;
                totalsamples += frame.Header.BlockSize;
            }
            TotalLength = totalLength;
            TotalSamples = totalsamples;
        }
예제 #22
0
 public FlacFrameHeader(Stream stream, FlacMetadataStreamInfo streamInfo)
     : this(stream, streamInfo, true)
 {
 }
예제 #23
0
        protected void StartScan(FlacMetadataStreamInfo streamInfo, FlacPreScanMethodMode method)
        {
            if (_isRunning)
                throw new Exception("Scan is already running.");

            _isRunning = true;

            if (method == FlacPreScanMethodMode.Async)
            {
                new Thread((o) =>
                {
                    Frames = RunScan(streamInfo);
                    _isRunning = false;
                }).Start();
            }
            else
            {
                Frames = ScanThisShit(streamInfo);
                _isRunning = false;
            }
        }
예제 #24
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FlacFrameHeader"/> class.
 /// </summary>
 /// <param name="stream">The underlying stream which contains the <see cref="FlacFrameHeader"/>.</param>
 /// <param name="streamInfo">The stream-info-metadata-block of the flac stream which provides some basic information about the flac framestream. Can be set to null.</param>
 public FlacFrameHeader(Stream stream, FlacMetadataStreamInfo streamInfo)
     : this(stream, streamInfo, true)
 {
 }
예제 #25
0
        private unsafe List<FlacFrameInformation> ScanThisShit(FlacMetadataStreamInfo streamInfo)
        {
            Stream stream = _stream;

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

            byte[] buffer = new byte[bufferSize];
            int read = 0;
            stream.Position = 4; //fLaC

            FlacMetadata.AllDataFromStream(stream);

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

            FlacFrameHeader header;
            FlacFrameHeader tmp = null;
            FlacFrameHeader baseHeader = null;

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

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

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

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

                stream.Position -= FlacConstant.FrameHeaderSize;
            }

            return frames;
        }
예제 #26
0
 public unsafe FlacFrameHeader(ref byte* buffer, FlacMetadataStreamInfo streamInfo, bool doCrc)
     : this(ref buffer, streamInfo, doCrc, true)
 {
 }
예제 #27
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;

            //skip ID3v2
            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);
                Debug.WriteLine("Flac StreamInfo found -> WaveFormat: " + _waveFormat);
                Debug.WriteLine("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) =>
                {
                    if (onscanFinished != null)
                        onscanFinished(e);
                };
                scan.ScanStream(_streamInfo, scanFlag);
                _scan = scan;
            }
        }
예제 #28
0
        private unsafe bool ParseHeader(ref byte *headerBuffer, FlacMetadataStreamInfo streamInfo)
        {
            const string loggerLocation = "FlacFrameHeader.ParseHeader(byte*, FlacMetadataStreamInfo)";
            int          val;

            if (headerBuffer[0] == 0xFF && headerBuffer[1] >> 1 == 0x7C) //sync bits
            {
                if ((headerBuffer[1] & 0x02) != 0)
                {
                    Error("Invalid FlacFrame. Reservedbit_0 is 1", loggerLocation);
                    return(false);
                }

                byte *        __headerbufferPtr = headerBuffer;
                FlacBitReader reader            = new FlacBitReader(__headerbufferPtr, 0);

                #region blocksize

                //blocksize
                val = headerBuffer[2] >> 4;
                int blocksize = -1;

                if (val == 0)
                {
                    Error("Invalid Blocksize value: 0", loggerLocation);
                    return(false);
                }
                if (val == 1)
                {
                    blocksize = 192;
                }
                else if (val >= 2 && val <= 5)
                {
                    blocksize = 576 << (val - 2);
                }
                else if (val == 6 || val == 7)
                {
                    _blocksizeHint = val;
                }
                else if (val >= 8 && val <= 15)
                {
                    blocksize = 256 << (val - 8);
                }
                else
                {
                    Error("Invalid Blocksize value: " + val, loggerLocation);
                    return(false);
                }
                BlockSize = blocksize;

                #endregion blocksize

                #region samplerate

                //samplerate
                val = headerBuffer[2] & 0x0F;
                int sampleRate = -1;

                if (val == 0)
                {
                    if (streamInfo != null)
                    {
                        sampleRate = streamInfo.SampleRate;
                    }
                    else
                    {
                        Error("Missing Samplerate. Samplerate Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return(false);
                    }
                }
                else if (val >= 1 && val <= 11)
                {
                    sampleRate = FlacConstant.SampleRateTable[val];
                }
                else if (val >= 12 && val <= 14)
                {
                    _sampleRateHint = val;
                }
                else
                {
                    Error("Invalid SampleRate value: " + val, loggerLocation);
                    return(false);
                }
                SampleRate = sampleRate;

                #endregion samplerate

                #region channels

                val = headerBuffer[3] >> 4; //cc: unsigned
                int channels;
                if ((val & 8) != 0)
                {
                    channels = 2;
                    if ((val & 7) > 2 || (val & 7) < 0)
                    {
                        Error("Invalid ChannelAssignment", loggerLocation);
                        return(false);
                    }
                    ChannelAssignment = (ChannelAssignment)((val & 7) + 1);
                }
                else
                {
                    channels          = val + 1;
                    ChannelAssignment = ChannelAssignment.Independent;
                }
                Channels = channels;

                #endregion channels

                #region bitspersample

                val = (headerBuffer[3] & 0x0E) >> 1;
                int bitsPerSample;
                if (val == 0)
                {
                    if (streamInfo != null)
                    {
                        bitsPerSample = streamInfo.BitsPerSample;
                    }
                    else
                    {
                        Error("Missing BitsPerSample. Index = 0 && streamInfoMetaData == null.", loggerLocation);
                        return(false);
                    }
                }
                else if (val == 3 || val >= 7 || val < 0)
                {
                    Error("Invalid BitsPerSampleIndex", loggerLocation);
                    return(false);
                }
                else
                {
                    bitsPerSample = FlacConstant.BitPerSampleTable[val];
                }

                BitsPerSample = bitsPerSample;

                #endregion bitspersample

                if ((headerBuffer[3] & 0x01) != 0) // reserved bit -> 0
                {
                    Error("Invalid FlacFrame. Reservedbit_1 is 1", loggerLocation);
                    return(false);
                }

                reader.ReadBits(32); //skip the first 4 bytes since they got already processed

                //BYTE 4

                #region utf8

                //variable blocksize
                if ((headerBuffer[1] & 0x01) != 0 ||
                    (streamInfo != null && streamInfo.MinBlockSize != streamInfo.MaxBlockSize))
                {
                    ulong samplenumber;
                    if (reader.ReadUTF8_64(out samplenumber) && samplenumber != ulong.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.VariableBlockSize;
                        SampleNumber     = (long)samplenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Samplenumber coding.", loggerLocation);
                        return(false);
                    }
                }
                else //fixed blocksize
                {
                    uint framenumber;

                    if (reader.ReadUTF8_32(out framenumber) && framenumber != uint.MaxValue)
                    {
                        BlockingStrategy = BlockingStrategy.FixedBlockSize;
                        FrameNumber      = (int)framenumber;
                    }
                    else
                    {
                        Error("Invalid UTF8 Framenumber coding.", loggerLocation);
                        return(false);
                    }
                }

                #endregion utf8

                #region read hints

                //blocksize am ende des frameheaders
                if (_blocksizeHint != 0)
                {
                    val = (int)reader.ReadBits(8);
                    if (_blocksizeHint == 7)
                    {
                        val = (val << 8) | (int)reader.ReadBits(8);
                    }
                    BlockSize = val + 1;
                }

                //samplerate
                if (_sampleRateHint != 0)
                {
                    val = (int)reader.ReadBits(8);
                    if (_sampleRateHint != 12)
                    {
                        val = (val << 8) | (int)reader.ReadBits(8);
                    }
                    if (_sampleRateHint == 12)
                    {
                        SampleRate = val * 1000;
                    }
                    else if (_sampleRateHint == 13)
                    {
                        SampleRate = val;
                    }
                    else
                    {
                        SampleRate = val * 10;
                    }
                }

                #endregion read hints

                if (DoCrc)
                {
                    var crc8 = Utils.CRC8.Instance.CalcCheckSum(reader.Buffer, 0, reader.Position);
                    Crc8 = (byte)reader.ReadBits(8);
                    if (Crc8 != crc8)
                    {
                        Error("CRC8 missmatch", loggerLocation);
                        return(false);
                    }
                }
                else
                {
                    Crc8 = (byte)reader.ReadBits(8);
                }

                headerBuffer += reader.Position;
                return(true);
            }

            Error("Invalid Syncbits", loggerLocation);
            return(false);
        }