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; }
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; }
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; }