private void WriteFrame(Frame frame, VirtualTrack track, long start, long end, int frameSize, long imageStartSample, long offset)
        {
            TrackFrame trackFrame = new TrackFrame(offset, frameSize, imageStartSample);
            trackFrame.imageBlockSize = frame.Header.BlockSize;
            trackFrame.startSample = sampleCount_;
            trackFrame.virtualOffset = track.Size;

            int count = (int)(end - start);

            int virtualSize;
            int sizeDifference = 0;
            if (frame.Header.BlockSize == count)
            {
                sizeDifference = flac.Io.UTF8Encoder.GetUtf8ULong(sampleCount_).Length - frame.Header.SampleIdSize;
                virtualSize = frameSize + sizeDifference;
            #if DEBUG
                frame.Header.StartingSampleNumber = sampleCount_;
                frame.Header.BlockingStrategy = FrameHeader.BLOCKING_STRATEGY_VARIABLE;

                outStream_.Writer.Truncate(0);
                frame.Write(outStream_);

                Debug.Assert(virtualSize == outStream_.Writer.Debug_BytesWritten);
            #endif
            }
            else
            {
                frame.Header.StartingSampleNumber = sampleCount_;
                frame.Header.BlockingStrategy = FrameHeader.BLOCKING_STRATEGY_VARIABLE;
                frame.Header.BlockSize = count;

                outStream_.Writer.Truncate(0);
                frame.Write(outStream_, (int)(start - imageStartSample), count);
                virtualSize = Convert.ToInt32(outStream_.Writer.Debug_BytesWritten);
                sizeDifference = virtualSize - frameSize;
            }
            trackFrame.sizeDifference = sizeDifference;
            track.Frames.Add(trackFrame.virtualOffset, trackFrame);

            track.Size += virtualSize;

            track.MinBlockSize = Math.Min(track.MinBlockSize, frame.Header.BlockSize);
            track.MaxBlockSize = Math.Max(track.MaxBlockSize, frame.Header.BlockSize);
            track.MinFrameSize = (int)Math.Min(track.MinFrameSize, virtualSize);
            track.MaxFrameSize = (int)Math.Max(track.MaxFrameSize, virtualSize);

            sampleCount_ += frame.Header.BlockSize;
        }
        private void ProcessFrame(FlacStream inStream, Frame frame, long offset)
        {
            long startSample = frame.Header.StartingSampleNumber;
            long endSample = startSample + frame.Header.BlockSize;
            int frameSize = (int)(inStream.Reader.Debug_BytesRead - offset);

            if (blockingStrategy_ == -1)
            {
                blockingStrategy_ = frame.Header.BlockingStrategy;
            }
            else
            {
                // whole stream must have the same blocking strategy
                Debug.Assert(frame.Header.BlockingStrategy == blockingStrategy_);
            }

            if (currentTrack_ != null)
            {
                long start = startSample;
                long end = endSample;

                if (start <= currentTrack_.EndSample && currentTrack_.EndSample <= end)
                {
                    end = currentTrack_.EndSample;
                    WriteFrame(frame, currentTrack_, start, end, frameSize, startSample, offset);
                    currentTrack_.TotalSamples = sampleCount_;

                    currentTrack_.Frames.Values[0].CalculateVirtualBlockSizeDifference(currentTrack_.StartSample, true);
                    currentTrack_.Frames.Values[currentTrack_.Frames.Count - 1].CalculateVirtualBlockSizeDifference(currentTrack_.EndSample, false);

                    RefreshFrame(inStream, ref frame, offset);
                    currentTrack_ = null;
                    goto loop;
                }
                else
                {
                    WriteFrame(frame, currentTrack_, start, end, frameSize, startSample, offset);
                    goto done;
                }
            }
            else
            {
                goto loop;
            }

            loop:
            foreach (ITrackInfo file in tracksInfo_)
            {
                long start = startSample;
                long end = endSample;
                if (start <= file.StartSample && file.StartSample <= end)
                {
                    VirtualTrack lastTrack = null;
                    if (virtualTracks_.Count > 0)
                    {
                        lastTrack = virtualTracks_[virtualTracks_.Count - 1];
                    }
                    if (lastTrack != null)
                    {
                        Debug.Assert(lastTrack.Frames.Values[lastTrack.Frames.Count - 1].imageEndSample == endSample);
                    }

                    currentTrack_ = new VirtualTrack();
                    currentTrack_.StartSample =file.StartSample;
                    currentTrack_.EndSample = file.EndSample;
                    currentTrack_.FileName = file.Name;
                    currentTrack_.Size = TRACK_HEADER_SIZE;
                    virtualTracks_.Add(currentTrack_);

                    sampleCount_ = 0;

                    start = file.StartSample;

                    bool next = false;
                    if (start <= file.EndSample && file.EndSample <= end)
                    {
                        // track ends in the same frame
                        end = file.EndSample;

                        // write (probably) partial first frame of track
                        WriteFrame(frame, currentTrack_, start, end, frameSize, startSample, offset);
                        RefreshFrame(inStream, ref frame, offset);
                        next = true;
                    }
                    else
                    {
                        // write (probably) partial first frame of track
                        WriteFrame(frame, currentTrack_, start, end, frameSize, startSample, offset);
                    }
                    if (next)
                    {
                        continue;
                    }
                    break;
                }
            }
            done:
            return;
        }
        private void RefreshFrame(FlacStream inStream, ref Frame frame, long offset)
        {
            inStream_.Reader.Seek(offset);

            frame = new Frame();
            frame.ReadHeader(inStream);
            frame.ReadData(inStream);
            frame.ReadFooter(inStream);
        }
 public FrameCallbackArgs(Frame frame, FlacStream stream)
 {
     frame_ = frame;
     stream_ = stream;
 }
Example #5
0
        private void WriteFrame(Frame frame, FrameHeader header, long start, long end)
        {
            frame.ReadData(stream_);
            frame.ReadFooter(stream_);

            long startSample = frame.Header.StartingSampleNumber;
            int count = (int)(end - start);

            header.StartingSampleNumber = sampleCount_;
            header.BlockingStrategy = FrameHeader.BLOCKING_STRATEGY_VARIABLE;

            if (count == header.BlockSize)
            {
                frame.Write(outStream_);
            }
            else
            {
                header.BlockSize = count;
                frame.Write(outStream_, (int)(start - startSample), count);
            }

            trackFrameCount_++;
            sampleCount_ += header.BlockSize;
        }
Example #6
0
        public void Decode()
        {
            signature_ = new Signature();
            signature_.Read(this);

            streamInfo_ = MetadataBlock.New(this) as MetadataBlockStreamInfo;
            Validation.IsValid(streamInfo_ != null);

            MetadataBlock block = streamInfo_;
            if (MetadataRead != null)
            {
                MetadataRead(streamInfo_);
            }

            while (!block.Header.IsLastMetadataBlock)
            {
                block = MetadataBlock.New(this);
                if (MetadataRead != null)
                {
                    MetadataRead(block);
                }
            }

            while (!reader_.Done)
            {
                Frame frame = new Frame();
                long offset = reader_.Debug_BytesRead;
                frame.ReadHeader(this);
                bool haveRead = false;
                if (BeforeFrameDataRead != null)
                {
                    FrameCallbackArgs a = new FrameCallbackArgs(frame, this);
                    a.Offset = offset;
                    BeforeFrameDataRead(a);
                    if (!a.ContinueDecoding)
                    {
                        break;
                    }
                    haveRead = a.HaveReadData;
                }
                if (!haveRead)
                {
                    frame.ReadData(this);
                    frame.ReadFooter(this);
                }
            }
        }
        // read n bytes of virtual track starting at x offset into provided buffer
        public int Read(byte[] bytes, long offset, int count)
        {
            count = Math.Min((int)(track_.Size - offset), count);

            int bytesToRead = count;
            long currentOffset = offset;
            long endOffset = Math.Max(currentOffset, offset + bytesToRead - 1);

            // if header, copy it from memory
            long max = Math.Min(endOffset + 1, header_.Length);
            while (currentOffset < max)
            {
                bytes[currentOffset - offset] = header_[currentOffset];
                currentOffset++;
                bytesToRead--;
            }

            if (bytesToRead <= 0)
            {
                goto exit;
            }

            List<TrackFrame> pairs;

            int currentIndex = GetOffsetPairs(bytesToRead, currentOffset, out pairs);
            foreach (TrackFrame op in pairs)
            {
                inStream_.Reader.Seek(op.imageOffset);
                Frame f = new Frame();
                f.ReadHeader(inStream_);
                f.ReadData(inStream_);
                f.ReadFooter(inStream_);

                f.Header.BlockingStrategy = FrameHeader.BLOCKING_STRATEGY_VARIABLE;
                f.Header.StartingSampleNumber = op.startSample;
                f.Header.BlockSize = op.virtualBlockSize;

                outStream_.Writer.Truncate(0);

                bool countFunction = false;
                if ((currentIndex == 0 && op.imageStartSample != track_.StartSample) || (currentIndex == track_.Frames.Count -1 &&  op.imageEndSample != track_.EndSample))
                {
                    // partial frame
                    long start = Math.Max(track_.StartSample, op.imageStartSample);
                    long end = Math.Min(track_.EndSample, op.imageEndSample);
                    f.Write(outStream_, (int)(start - op.imageStartSample), (int)(end - start));
                    countFunction = true;
                }
                else
                {
                    f.Write(outStream_);
                }

                byte[] data = ReadAllBytes();

                max = Math.Min(endOffset + 1, op.virtualOffset + op.virtualSize);
                if (!countFunction)
                {
                    Debug.Assert(data.Length == op.virtualSize);
                }

                int i = Convert.ToInt32(currentOffset - op.virtualOffset);
                while (currentOffset < max)
                {
                    bytes[currentOffset - offset] = data[i];
                    i++;
                    currentOffset++;
                    bytesToRead--;
                }

                if (bytesToRead <= 0)
                {
                    break;
                }
                currentIndex++;
            }

            exit:
            return count;
        }