Example #1
0
        internal bool TryInit()
        {
            // try to process the stream header...
            if (!ProcessStreamHeader(_packetProvider.PeekNextPacket()))
            {
                return(false);
            }

            // seek past the stream header packet
            _packetProvider.GetNextPacket().Done();

            // load the comments header...
            var packet = _packetProvider.GetNextPacket();

            if (!LoadComments(packet))
            {
                throw new InvalidDataException("Comment header was not readable!");
            }
            packet.Done();

            // load the book header...
            packet = _packetProvider.GetNextPacket();
            if (!LoadBooks(packet))
            {
                throw new InvalidDataException("Book header was not readable!");
            }
            packet.Done();

            // get the decoding logic bootstrapped
            InitDecoder();

            return(true);
        }
Example #2
0
        /// <summary>
        /// Seeks the stream for a valid packet at the specified granule position.
        /// </summary>
        /// <param name="granulePosition">The granule position.</param>
        private void SeekToGranulePosition(long granulePosition)
        {
            if (!CanSeek)
            {
                throw new InvalidOperationException("Stream is not seekable.");
            }

            if (granulePosition < 0 || granulePosition > GranuleCount)
            {
                throw new ArgumentOutOfRangeException(nameof(granulePosition));
            }

            // Find a packet based on offset and return 1 in the callback if the packet is valid
            var foundPacket = _packetProvider.FindPacket(granulePosition, GetPacketLength);

            // Check of the found packet is valid
            if (foundPacket == null || foundPacket.IsEndOfStream)
            {
                _endOfStream    = true;
                _nextDataPacket = null;
                return;
            }

            // Just seek to this found packet and get the previous packet (preRoll = 1)
            _packetProvider.SeekToPacket(foundPacket, 1);

            // Update the PageGranulePosition to the position from this next packet which will be retrieved by the next QueueNextPacket call
            PageGranulePosition = _packetProvider.PeekNextPacket().PageGranulePosition;

            // Reset the state from the decoder to start processing a fresh stream
            _decoder.ResetState();
        }
Example #3
0
        private void SkipOpusTags(IPacketProvider packetProvider)
        {
            DataPacket packet = packetProvider.PeekNextPacket();
            byte[] buffer = GetPacketData(packet);

            if (Encoding.UTF8.GetString(buffer, 0, 8) == "OpusTags")
            {
                packetProvider.GetNextPacket();
            }
        }
Example #4
0
        internal void SeekTo(long granulePos)
        {
            if (!_packetProvider.CanSeek)
            {
                throw new NotSupportedException();
            }

            if (granulePos < 0)
            {
                throw new ArgumentOutOfRangeException("granulePos");
            }

            var targetPacketIndex = 3;

            if (granulePos > 0)
            {
                var idx = _packetProvider.FindPacket(granulePos, GetPacketLength);
                if (idx == -1)
                {
                    throw new ArgumentOutOfRangeException("granulePos");
                }
                targetPacketIndex = idx - 1;  // move to the previous packet to prime the decoder
            }

            // seek the stream
            _packetProvider.SeekToPacket(targetPacketIndex);

            // now figure out where we are and how many samples we need to discard...
            // note that we use the granule position of the "current" packet, since it will be discarded no matter what

            // get the packet that we'll decode next
            var dataPacket = _packetProvider.PeekNextPacket();

            // now read samples until we are exactly at the granule position requested
            CurrentPosition = dataPacket.GranulePosition;
            var cnt = (int)((granulePos - CurrentPosition) * _channels);

            if (cnt > 0)
            {
                var seekBuffer = new float[cnt];
                while (cnt > 0)
                {
                    var temp = ReadSamples(seekBuffer, 0, cnt);
                    if (temp == 0)
                    {
                        break;              // we're at the end...
                    }
                    cnt -= temp;
                }
            }
        }
        internal bool TryInit()
        {
            if (!ProcessStreamHeader(_packetProvider.PeekNextPacket()))
            {
                return(false);
            }
            _packetProvider.GetNextPacket().Done();
            DataPacket nextPacket = _packetProvider.GetNextPacket();

            if (!LoadComments(nextPacket))
            {
                throw new InvalidDataException("Comment header was not readable!");
            }
            nextPacket.Done();
            nextPacket = _packetProvider.GetNextPacket();
            if (!LoadBooks(nextPacket))
            {
                throw new InvalidDataException("Book header was not readable!");
            }
            nextPacket.Done();
            InitDecoder();
            return(true);
        }
        internal StreamDecoder(IPacketProvider packetProvider, IFactory factory)
        {
            _packetProvider = packetProvider ?? throw new ArgumentNullException(nameof(packetProvider));
            _factory        = factory ?? throw new ArgumentNullException(nameof(factory));

            _stats = new StreamStats();

            _currentPosition = 0L;
            ClipSamples      = true;

            var packet = _packetProvider.PeekNextPacket();

            if (!ProcessHeaderPackets(packet))
            {
                _packetProvider = null !;
                packet?.Reset();

                throw GetInvalidStreamException(packet);
            }
        }