////------------------------------------------------------------------------------------------------------------------------------ public static FlacRicePartition Read(StreamBuffer sb, int partitionNumber, int partitionOrder, int predictOrder, int blockSize, FlacResidualCodingMethod codingMethod) { FlacRicePartition ricePartition = new FlacRicePartition { _riceParameter = sb.ReadBigEndianInt32(), _codingMethod = codingMethod }; int riceParameter = ricePartition._riceParameter & ((codingMethod == FlacResidualCodingMethod.PartitionedRice) ? 0x1F : 0xF); if (partitionOrder == 0) ricePartition.Samples = blockSize - predictOrder; else if (partitionNumber == 0) ricePartition.Samples = (blockSize >> partitionOrder) - predictOrder; else ricePartition.Samples = blockSize >> partitionOrder; ricePartition.Residuals = new int[ricePartition.Samples]; if ((riceParameter < 0xF) || ((codingMethod == FlacResidualCodingMethod.PartitionedRice2) && (riceParameter < 0x1F))) { for (int i = 0; i < ricePartition.Samples; i++) { long msbs = sb.ReadUnaryInt(); long lsbs = sb.ReadBigEndianInt32() & (0xFFFFFFFF >> (32 - riceParameter)); long value = (msbs << riceParameter) | lsbs; ricePartition.Residuals[i] = ((value & 0x01) == 0x01) ? -((int)(value >> 1)) - 1 : (int)(value >> 1); } } else { // residuals in unencoded form, sample size read from the next 5 // bits in the stream. int size = sb.ReadBigEndianInt32(); for (int i = 0; i < ricePartition.Samples; i++) ricePartition.Residuals[i] = sb.ReadBigEndianInt32(); } return ricePartition; }
private bool ReadFieldInstance(StreamBuffer sb, long maximumFieldSize) { if (sb == null) throw new ArgumentNullException("sb"); string identifier = sb.ReadString(FieldIdentifierLength); string strFieldSize = sb.ReadString(FieldSizeLength); int fieldSize; if (!Int32.TryParse(strFieldSize, out fieldSize)) { #if DEBUG return false;//throw new InvalidDataException(String.Format("Size value for field {0} is not an int: {1}", identifier, strFieldSize)); #else return false; #endif } Identifier = identifier; _data = new byte[fieldSize]; sb.Read(_data, fieldSize); if (!IsValidData(_data)) return false; Data = _data; return true; }
/// <summary> /// Initializes a new instance of the <see cref="BitStream"/> class and sets the specified stream to use as backing data. /// </summary> /// <param name="stream">The stream to use as backing data.</param> public BitStream(Stream stream) { if (stream == null) throw new ArgumentNullException("stream"); _sb = new StreamBuffer(stream); }
public void LengthTest() { byte[] value = new byte[] { 0x01, 0x02, 0x10 }; StreamBuffer target = new StreamBuffer(value); long actual= target.Length; Assert.AreEqual(actual, value.Length); }
public void CanWriteTest() { StreamBuffer target = new StreamBuffer(); // TODO: Initialize to an appropriate value bool actual; actual = target.CanWrite; Assert.Inconclusive("Verify the correctness of this test method."); }
/// <summary> /// Initializes a new instance of the <see cref="VbriHeader"/> class. /// </summary> /// <param name="firstFrame">The first frame.</param> /// <param name="firstFrameBuffer">The first frame buffer.</param> /// <param name="offset">The offset.</param> public VbriHeader(MpaFrame firstFrame, StreamBuffer firstFrameBuffer, long offset) : base(firstFrame, firstFrameBuffer, offset, VbrHeaderType.Vbri) { /* FhG VBRI Header size description 4 'VBRI' (ID) 2 version 2 delay 2 quality 4 # bytes 4 # frames 2 table size (for TOC) 2 table scale (for TOC) 2 size of a table entry (max. size = 4 byte (must be stored in an integer)) 2 frames per table entry ?? dynamic table consisting out of frames with size 1-4 whole length in table size! (for TOC) */ // name Name = firstFrameBuffer.ReadString(4); // version Version = (short)firstFrameBuffer.ReadBigEndianInt16(); // delay _delay = firstFrameBuffer.ReadBigEndianInt16(); // quality Quality = firstFrameBuffer.ReadBigEndianInt16(); // size of the file, in bytes, of all the data FileSize = firstFrameBuffer.ReadBigEndianInt32(); // amount of frames FrameCount = firstFrameBuffer.ReadBigEndianInt32(); // number of entries in the table (for TOC) TableEntries = (short)firstFrameBuffer.ReadBigEndianInt16(); // table scale (for TOC) TableScale = (short)firstFrameBuffer.ReadBigEndianInt16(); // size of a table entry (in bytes) TableEntrySize = (short)firstFrameBuffer.ReadBigEndianInt16(); // frames per table entry FramesPerTableEntry = (short)firstFrameBuffer.ReadBigEndianInt16(); // dynamic table consisting out of frames TableLength = TableEntries * TableEntrySize; Toc = new int[TableEntries + 1]; for (int i = 0; i <= TableEntries; i++) { int value = firstFrameBuffer.ReadBigEndianInt(TableEntrySize); Toc[i] = value * TableScale; } _totalLengthMilliseconds = firstFrame.AudioLength * FrameCount; }
////------------------------------------------------------------------------------------------------------------------------------ private static Lyrics3v2Field ReadField(StreamBuffer sb, long maximumFieldSize) { if (sb == null) throw new ArgumentNullException("sb"); string identifier = sb.ReadString(FieldIdentifierLength, false, false); Lyrics3v2Field field = GetField(identifier); return field.ReadFieldInstance(sb, maximumFieldSize) ? field : null; }
/// <summary> /// Initializes a new instance of the <see cref="BitStream"/> class /// based on the specified byte array with an expandable capacity, using <see cref="System.IO.MemoryStream"/> as backing data. /// </summary> /// <param name="buffer">The array of unsigned bytes from which to create the current stream.</param> public BitStream(byte[] buffer) { if (buffer == null) throw new ArgumentNullException("buffer"); _sb = new StreamBuffer(buffer.Length); _sb.Write(buffer, 0, buffer.Length); _sb.Position -= buffer.Length; }
////------------------------------------------------------------------------------------------------------------------------------ /// <inheritdoc /> public override byte[] ToByteArray() { using (StreamBuffer sb = new StreamBuffer()) { sb.Write(base.ToByteArray()); sb.WriteBigEndianBytes(UnencodedConstantValue, SampleSize / 8); return sb.ToByteArray(); } }
////------------------------------------------------------------------------------------------------------------------------------ public static FlacResidual Read(StreamBuffer sb, int blockSize, int order) { FlacResidual residual = new FlacResidual { _values = sb.ReadByte() }; int partitions = 1 << residual.PartitionOrder; residual.RicePartitions = new FlacRicePartition[partitions]; for (int i = 0; i < partitions; i++) residual.RicePartitions[i] = FlacRicePartition.Read(sb, i, residual.PartitionOrder, order, blockSize, residual.CodingMethod); return residual; }
/// <summary> /// Initializes a new instance of the <see cref="XingHeader"/> class. /// </summary> /// <param name="firstFrame">The first frame.</param> /// <param name="firstFrameBuffer">The first frame buffer.</param> /// <param name="offset">The offset.</param> public XingHeader(MpaFrame firstFrame, StreamBuffer firstFrameBuffer, long offset) : base(firstFrame, firstFrameBuffer, offset, VbrHeaderType.Xing) { /* XING VBR-Header size description 4 'Xing' or 'Info' 4 flags (indicates which fields are used) 4 frames (optional) 4 bytes (optional) 100 toc (optional) 4 a VBR quality indicator: 0=best 100=worst (optional) --------- + 120 bytes * * NOTE: the frames (frameCount) in the XING header does not include its own frame. * So the total frames is actually XING framecount + 1 */ // name of the tag as found in the file Name = firstFrameBuffer.ReadString(4); // The flags indicate which fields are used in the XING header Flags = firstFrameBuffer.ReadBigEndianInt32(); // Extract total frames in the file (XING header excludes it's own frame) if ((Flags & XingHeaderFlags.FrameCountFlag) != 0) FrameCount = firstFrameBuffer.ReadBigEndianInt32(); // Extract size of the file, in bytes if ((Flags & XingHeaderFlags.FileSizeFlag) != 0) FileSize = firstFrameBuffer.ReadBigEndianInt32(); // Extract TOC (Table of Contents) for more accurate seeking if ((Flags & XingHeaderFlags.TocFlag) != 0) { Toc = new int[100]; for (int i = 0; i < 100; i++) Toc[i] = firstFrameBuffer.ReadByte(); } if ((Flags & XingHeaderFlags.VbrScaleFlag) != 0) Quality = firstFrameBuffer.ReadBigEndianInt32(); // The LAME tag is always 120 bytes after the XING header - regardless of which fields are used LameTag = LameTag.FindTag(firstFrameBuffer, offset + 120); }
/// <summary> /// Initializes a new instance of the <see cref="VbrHeader"/> class. /// </summary> /// <param name="firstFrame">The first frame.</param> /// <param name="firstFrameBuffer">The first frame buffer.</param> /// <param name="offset">The offset.</param> /// <param name="headerType">Type of the header.</param> protected VbrHeader(MpaFrame firstFrame, StreamBuffer firstFrameBuffer, long offset, VbrHeaderType headerType) { if (firstFrame == null) throw new ArgumentNullException("firstFrame"); if (firstFrameBuffer == null) throw new ArgumentNullException("firstFrameBuffer"); ////if (headerType == null) ////throw new ArgumentNullException("headerType"); // first frame contains the vbr header FirstFrame = firstFrame; // Offset of this header in the first frame. Offset = offset; // VBR Header type, currently only XING and VBRI HeaderType = headerType; }
/// <summary> /// Finds the <see cref="VbriHeader"/> header within the <paramref name="firstFrame"/>. /// </summary> /// <param name="firstFrame">The first frame.</param> /// <returns>The VBRI header if found; otherwise, null.</returns> /// <remarks> /// The VBRI header is located exactly 32 bytes after the end of the first MPEG audio header in the file. /// It will compare the first 4 bytes against the <see cref="HeaderIndicator"/> /// to see if the header contains a <see cref="VbriHeader"/> or not. /// </remarks> public static new VbriHeader FindHeader(MpaFrame firstFrame) { if (firstFrame == null) throw new ArgumentNullException("firstFrame"); using (StreamBuffer buffer = new StreamBuffer()) { byte[] data = firstFrame.ToByteArray(); buffer.Write(data); // 32 bytes = data indicating silence const long Offset = MpaFrame.FrameHeaderSize + SilenceDataSize; buffer.Seek(Offset, SeekOrigin.Begin); string tagName = buffer.ReadString(4, false, false); return String.Compare(tagName, HeaderIndicator, StringComparison.OrdinalIgnoreCase) == 0 ? new VbriHeader(firstFrame, buffer, Offset) : null; } }
/// <inheritdoc/> public override byte[] ToByteArray() { using (StreamBuffer buf = new StreamBuffer()) { buf.WriteString(Name); buf.WriteBigEndianInt32(Flags); if ((Flags & XingHeaderFlags.FrameCountFlag) != 0) buf.WriteBigEndianInt32(FrameCount); if ((Flags & XingHeaderFlags.FileSizeFlag) != 0) buf.WriteBigEndianInt32(FileSize); // Extract TOC (Table of Contents) for more accurate seeking if ((Flags & XingHeaderFlags.TocFlag) != 0) { for (int i = 0; i < 100; i++) buf.WriteByte((byte)Toc[i]); } if ((Flags & XingHeaderFlags.VbrScaleFlag) != 0) buf.WriteBigEndianInt32(Quality); return buf.ToByteArray(); } }
/// <summary> /// Finds the <see cref="VbriHeader"/> header within the <paramref name="firstFrame"/>. /// </summary> /// <param name="firstFrame">The first frame.</param> /// <returns>The VBRI header if found; otherwise, null.</returns> /// <remarks> /// The XING header is located after the side information in Layer III in the first MPEG audio header in the file. /// It will compare the first 4 bytes against the <see cref="VbrHeaderIndicator"/> /// to see if the header contains a <see cref="XingHeader"/> or not. /// </remarks> public static new XingHeader FindHeader(MpaFrame firstFrame) { if (firstFrame == null) throw new ArgumentNullException("firstFrame"); long offset = MpaFrame.FrameHeaderSize + firstFrame.SideInfoSize; using (StreamBuffer buffer = new StreamBuffer()) { byte[] data = firstFrame.ToByteArray(); buffer.Write(data); buffer.Seek(offset, SeekOrigin.Begin); string tagName = buffer.ReadString(4, false, false); if ((String.Compare(tagName, VbrHeaderIndicator, StringComparison.OrdinalIgnoreCase) == 0) || (String.Compare(tagName, CbrHeaderIndicator, StringComparison.OrdinalIgnoreCase) == 0)) return new XingHeader(firstFrame, buffer, offset); } return null; }
/// <summary> /// Reads a <see cref="MpaFrame"/> from a <see cref="Stream"/>. /// </summary> /// <param name="stream">The stream.</param> /// <returns> /// true if found; otherwise, null. /// </returns> /// <exception cref="System.ArgumentNullException">Thrown if stream is null.</exception> private bool ReadFrame(StreamBuffer stream) { if (stream == null) throw new ArgumentNullException("stream"); StartOffset = stream.Position; if (!ParseHeader(stream)) return false; int frameLength = FrameLength, audioDataLength = 0; if (frameLength > FrameHeaderSize) audioDataLength = frameLength - FrameHeaderSize; if (audioDataLength == 0) return true; if ((stream.Length - stream.Position) < audioDataLength) { // Truncated audio data. audioDataLength = (int)(stream.Length - stream.Position); } AudioData = new byte[audioDataLength]; int bytesDataRead = stream.Read(AudioData, 0, audioDataLength); // Read the CRC // Create a buffer to read the CRC stored after the frame (2 bytes) if (bytesDataRead >= 2) { byte[] crc = new byte[2]; Buffer.BlockCopy(AudioData, 0, crc, 0, 2); Crc = StreamBuffer.SwitchEndianness(BitConverter.ToInt16(crc, 0)); } EndOffset = stream.Position; return true; }
private static string ReadTextField(StreamBuffer sb) { if (sb == null) throw new ArgumentNullException("sb"); int size = sb.ReadInt16(); return sb.ReadString(size); }
/// <inheritdoc /> public byte[] ToByteArray() { using (StreamBuffer sb = new StreamBuffer()) { sb.WriteString(Identifier); FlacStreamInfoMetadataBlock streamInfoMetadataBlock = StreamInfoMetadataBlocks.FirstOrDefault(); if (streamInfoMetadataBlock != null) sb.Write(streamInfoMetadataBlock.ToByteArray()); foreach (FlacMetadataBlock metadataBlock in MetadataBlocks.Where(m => !ReferenceEquals(m, streamInfoMetadataBlock))) sb.Write(metadataBlock.ToByteArray()); foreach (FlacFrame frame in Frames) sb.Write(frame.ToByteArray()); return sb.ToByteArray(); } }
private static ApeHeader ReadHeader(StreamBuffer stream, long startHeaderPosition, long endHeaderPosition) { if (stream == null) throw new ArgumentNullException("stream"); stream.Position = startHeaderPosition; while (startHeaderPosition < endHeaderPosition) { int y = 0; while (stream.ReadByte() == TagIdentifierBytes[y++]) { startHeaderPosition++; if (y != TagIdentifierBytes.Length) continue; ApeHeader hdr = new ApeHeader { Position = stream.Position - TagIdentifierBytes.Length, Version = (ApeVersion)(stream.ReadLittleEndianInt32() / 1000), Size = stream.ReadLittleEndianInt32(), FrameCount = stream.ReadLittleEndianInt32(), Flags = stream.ReadLittleEndianInt32(), ReservedBytes = new byte[8] }; stream.Read(hdr.ReservedBytes, 8); if (IsValidTag(hdr)) return hdr; startHeaderPosition -= ApeTag.HeaderSize; stream.Position = startHeaderPosition + 1; break; } startHeaderPosition++; } return null; }
private static MusicMatchHeader ReadHeader(StreamBuffer stream, TagOrigin tagOrigin) { if (stream == null) throw new ArgumentNullException("stream"); long startPosition = stream.Position; long streamLength = stream.Length; if (streamLength < MusicMatchTag.HeaderSize) return null; if (tagOrigin == TagOrigin.Start) { // Look for a header at the current position long startPositionHeader = startPosition; long endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength); MusicMatchHeader header = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.Start); if (header != null) return header; // Look for a header past the current position startPositionHeader = endPositionHeader; endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength); header = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.Start); if (header != null) return header; } else if (tagOrigin == TagOrigin.End) { // Look for a footer before the current position long startPositionHeader = Math.Max(startPosition - HeaderIdentifierBytes.Length, 0); long endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength); MusicMatchHeader footer = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.End); if (footer != null) return footer; // Look for a footer before the previous start position startPositionHeader = Math.Max(startPositionHeader - HeaderIdentifierBytes.Length, 0); endPositionHeader = Math.Min(startPositionHeader + HeaderIdentifierBytes.Length, streamLength); footer = ReadHeaderFooter(stream, startPositionHeader, endPositionHeader, HeaderIdentifierBytes, TagOrigin.End); if (footer != null) return footer; } return null; }
////------------------------------------------------------------------------------------------------------------------------------ private bool ReadFrame(StreamBuffer sb) { if (sb == null) throw new ArgumentNullException("sb"); StartOffset = sb.Position; if (!ReadHeader(sb)) return false; for (int channel = 0; channel < Channels; channel++) { FlacSubFrame subFrame = FlacSubFrame.ReadFrame(sb, channel, this); _subFrames.Add(subFrame); } _crc16 = sb.ReadBigEndianInt16(); int crc16 = Crc16.Calculate(new byte[0]); if (_crc16 != crc16) throw new InvalidDataException("Corrupt CRC16."); EndOffset = sb.Position; return true; }
/// <summary> /// Reads the header. /// </summary> /// <param name="sb">The <see cref="StreamBuffer"/>.</param> /// <returns> /// true if the header is read and valid; otherwise, false. /// </returns> /// <exception cref="System.ArgumentNullException">Thrown if <paramref name="sb"/> is null.</exception> private bool ReadHeader(StreamBuffer sb) { if (sb == null) throw new ArgumentNullException("sb"); long startPosition = sb.Position; // Sync code '11111111111110' _header = sb.ReadBigEndianInt32(); if (((_header >> 18) & FrameSync) != FrameSync) return false; /* Blocking strategy: •0 : fixed-block size stream; frame header encodes the frame number •1 : variable-block size stream; frame header encodes the sample number */ long num = ReadBigEndianUtf8Int64(sb, out _sampleFrameNumberBytes); switch (BlockingStrategy) { case FlacBlockingStrategy.FixedBlocksize: Samples = num; FrameNumber = num * (FlacStream.StreamInfoMetadataBlocks.Any() ? FlacStream.StreamInfoMetadataBlocks.First().MinimumBlockSize : 1); break; case FlacBlockingStrategy.VariableBlocksize: Samples = num; FrameNumber = -1; break; } /* Block size in inter-channel samples: •0000 : reserved •0001 : 192 samples •0010-0101 : 576 * (2 ^ (n - 2)) samples, i.e. 576/1152/2304/4608 •0110 : get 8 bit (block size - 1) from end of header •0111 : get 16 bit (block size - 1) from end of header •1000-1111 : 256 * (2 ^ (n - 8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/3276 */ int blockSize = (_header >> 12) & 0xF; switch (blockSize) { case 0x01: BlockSize = 192; break; case 0x02: case 0x03: case 0x04: case 0x05: BlockSize = 576 << (blockSize - 2); break; case 0x06: BlockSize = sb.ReadByte() + 1; break; case 0x07: BlockSize = sb.ReadBigEndianInt16() + 1; break; default: BlockSize = 256 << (blockSize - 8); break; } /* Sample rate: •0000 : get from STREAMINFO metadata block •0001 : 88.2kHz •0010 : 176.4kHz •0011 : 192kHz •0100 : 8kHz •0101 : 16kHz •0110 : 22.05kHz •0111 : 24kHz •1000 : 32kHz •1001 : 44.1kHz •1010 : 48kHz •1011 : 96kHz •1100 : get 8 bit sample rate (in kHz) from end of header •1101 : get 16 bit sample rate (in Hz) from end of header •1110 : get 16 bit sample rate (in tens of Hz) from end of header •1111 : invalid, to prevent sync-fooling string of 1s */ int samplingRate = (_header >> 8) & 0xF; if (samplingRate == 0x00) { SamplingRate = FlacStream.StreamInfoMetadataBlocks.Any() ? FlacStream.StreamInfoMetadataBlocks.First().SampleRate : 0; } else if (samplingRate <= 0x0B) { SamplingRate = SampleRates[samplingRate]; } else { switch (samplingRate) { case 0x0C: // Sample rate in kHz SamplingRate = sb.ReadByte() * 1000; break; case 0x0D: // Sample rate in Hz SamplingRate = sb.ReadBigEndianInt16(); break; case 0x0E: // Sample rate in 10s of Hz SamplingRate = sb.ReadBigEndianInt16() * 10; break; } } /* Channel assignment •0000-0111 : (number of independent channels)-1. Where defined, the channel order follows SMPTE/ITU-R recommendations. The assignments are as follows: ◦1 channel: mono ◦2 channels: left, right ◦3 channels: left, right, center ◦4 channels: front left, front right, back left, back right ◦5 channels: front left, front right, front center, back/surround left, back/surround right ◦6 channels: front left, front right, front center, LFE, back/surround left, back/surround right ◦7 channels: front left, front right, front center, LFE, back center, side left, side right ◦8 channels: front left, front right, front center, LFE, back left, back right, side left, side right •1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel •1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel •1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel •1011-1111 : reserved */ int channelAssignment = (_header >> 4) & 0xF; if (channelAssignment < 0x08) { ChannelAssignment = FlacChannelAssignment.Independent; Channels = channelAssignment + 1; } else { Channels = 2; switch (channelAssignment) { case 0x08: ChannelAssignment = FlacChannelAssignment.LeftSide; break; case 0x09: ChannelAssignment = FlacChannelAssignment.RightSide; break; case 0x0A: ChannelAssignment = FlacChannelAssignment.MidSide; break; } } /* Sample size in bits: •000 : get from STREAMINFO metadata block •001 : 8 bits per sample •010 : 12 bits per sample •011 : reserved •100 : 16 bits per sample •101 : 20 bits per sample •110 : 24 bits per sample •111 : reserved */ int sampleSize = (_header >> 0x01) & 0x07; SampleSize = (sampleSize == 0x00) ? (FlacStream.StreamInfoMetadataBlocks.Any() ? FlacStream.StreamInfoMetadataBlocks.First().BitsPerSample : 0) : SampleSizes[sampleSize]; _crc8 = sb.ReadByte(); long endPosition = sb.Position; long length = endPosition - startPosition; byte[] crcBytes = new byte[length]; sb.Position -= length; sb.Read(crcBytes, (int)length); byte crc8 = Crc8.Calculate(crcBytes); if (_crc8 != crc8) throw new InvalidDataException("Corrupt CRC8."); return true; }
////------------------------------------------------------------------------------------------------------------------------------ private static long ReadBigEndianUtf8Int64(StreamBuffer sb, out byte[] utf8Bytes) { //// Decoded long range Coded value //// 0000 0000 ・00 0000 007F 0xxxxxxx //// 0000 0080 ・00 0000 07FF 110xxxxx 10xxxxxx //// 0000 0800 ・00 0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx //// 0001 0000 ・00 001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx //// 0020 0000 ・00 03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx //// 0400 0000 ・00 7FFF FFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx //// 8000 0000 ・0F FFFF FFFF 11111110 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // Where xxx represent the bits in the uncoded value, in the same order. const int ByteCountMask = 0x80; // 10000000 const int ByteMask = 0x3F; // 00111111 int byteCount = 1; long value = sb.ReadByte(); if (value > ByteCountMask) { int bytes = 0; while (((value << bytes) & ByteCountMask) == ByteCountMask) bytes++; value &= ByteMask >> (bytes - 1); for (int i = bytes - 1; i > 0; i--) value = (value << (6 * i)) | ((long)sb.ReadByte() & ByteMask); byteCount += bytes - 1; } sb.Position -= byteCount; utf8Bytes = new byte[byteCount]; sb.Read(utf8Bytes, byteCount); return value; }
/// <inheritdoc/> public override byte[] ToByteArray() { using (StreamBuffer buffer = new StreamBuffer()) { buffer.WriteString(Name); buffer.WriteBigEndianInt16(Version); buffer.WriteBigEndianInt16((short)_delay); buffer.WriteBigEndianInt16((short)Quality); buffer.WriteBigEndianInt32(FileSize); buffer.WriteBigEndianInt32(FrameCount); buffer.WriteBigEndianInt16(TableEntries); buffer.WriteBigEndianInt16(TableScale); buffer.WriteBigEndianInt16(TableEntrySize); buffer.WriteBigEndianInt16(FramesPerTableEntry); for (int i = 0; i <= TableEntries; i++) buffer.WriteBigEndianBytes(Toc[i] / TableScale, TableEntrySize); return buffer.ToByteArray(); } }
////------------------------------------------------------------------------------------------------------------------------------ /// <summary> /// Reads the specified stream buffer. /// </summary> /// <param name="sb">The stream buffer.</param> /// <param name="sampeSize">Size of the sample.</param> /// <param name="blockSize">Size of the block.</param> protected override void Read(StreamBuffer sb, int sampeSize, int blockSize) { UnencodedWarmUpSamples = new int[Order]; for (int i = 0; i < Order; i++) UnencodedWarmUpSamples[i] = sb.ReadBigEndianInt32(); int other = sb.ReadBigEndianInt16(); QuantizedCoefficientsPrecision = (other & 0xF) + 1; QuantizedCoefficientShift = (other >> 4) & 0x1F; UnencodedPredictorCoefficients = new int[Order]; for (int i = 0; i < Order; i++) UnencodedPredictorCoefficients[i] = sb.ReadBigEndianInt32(); Residual = FlacResidual.Read(sb, blockSize, Order); }
/// <summary> /// Returns the frame in a byte array. /// </summary> /// <returns>The frame in a byte array.</returns> public byte[] ToByteArray() { using (StreamBuffer buffer = new StreamBuffer()) { buffer.Write(_header); buffer.Write(AudioData); return buffer.ToByteArray(); } }
/// <summary> /// Returns the frame in a byte array. /// </summary> /// <returns>The frame in a byte array.</returns> public byte[] ToByteArray() { using (StreamBuffer sb = new StreamBuffer()) { sb.WriteBigEndianInt32(_header); sb.Write(_sampleFrameNumberBytes); int blockSize = (_header >> 12) & 0xF; switch (blockSize) { case 0x06: sb.WriteByte((byte)(BlockSize - 1)); break; case 0x07: sb.WriteBigEndianInt16((short)(BlockSize - 1)); break; } int samplingRate = (_header >> 8) & 0xF; switch (samplingRate) { case 0x0C: sb.WriteByte((byte)(SamplingRate / 1000)); break; case 0x0D: sb.WriteBigEndianInt16((short)SamplingRate); break; case 0x0E: sb.WriteBigEndianInt16((short)(SamplingRate / 10)); break; } sb.WriteByte((byte)_crc8); foreach (FlacSubFrame subFrame in SubFrames) sb.Write(subFrame.ToByteArray()); sb.WriteBigEndianInt16((short)_crc16); return sb.ToByteArray(); } }
private static MusicMatchHeader ReadHeaderFooter(StreamBuffer stream, long startHeaderPosition, long endHeaderPosition, IList<byte> identifierBytes, TagOrigin tagOrigin) { if (stream == null) throw new ArgumentNullException("stream"); stream.Position = startHeaderPosition; while (startHeaderPosition < endHeaderPosition) { int y = 0; while (stream.ReadByte() == identifierBytes[y++]) { startHeaderPosition++; if (y != identifierBytes.Count) continue; if (tagOrigin == TagOrigin.Start) { MusicMatchHeader header = new MusicMatchHeader { Position = stream.Position - identifierBytes.Count, Padding1 = new byte[2], Padding2 = new byte[2], Padding3 = new byte[2], SpacePadding2 = new byte[226] }; // 0x00 0x00 Padding stream.Read(header.Padding1, header.Padding1.Length); // <8-byte numerical ASCII string> header.XingEncoderVersion = stream.ReadString(8); // 0x00 0x00 Padding stream.Read(header.Padding2, header.Padding2.Length); // Xing encoder version <8-byte numerical ASCII string> header.MusicMatchVersion = stream.ReadString(8); // 0x00 0x00 Padding stream.Read(header.Padding3, header.Padding3.Length); // Space padding <226 * 0x20 > stream.Read(header.SpacePadding2, header.SpacePadding2.Length); ValidateHeader(header, null); return header; } if (tagOrigin == TagOrigin.End) { MusicMatchHeader footer = new MusicMatchHeader { Position = stream.Position - identifierBytes.Count, SpacePadding1 = new byte[13], SpacePadding2 = new byte[12] }; // Space padding <13 * 0x20> stream.Read(footer.SpacePadding1, 13); // version <4-byte numerical ASCII string> e.g. 3.05 footer.MusicMatchVersion = stream.ReadString(4); // Space padding <12 * 0x20> stream.Read(footer.SpacePadding2, 12); ValidateHeader(null, footer); return footer; } } startHeaderPosition++; } return null; }
////------------------------------------------------------------------------------------------------------------------------------ /// <summary> /// Reads the specified stream buffer. /// </summary> /// <param name="sb">The stream buffer.</param> /// <param name="sampeSize">Size of the sample.</param> /// <param name="blockSize">Size of the block.</param> protected override void Read(StreamBuffer sb, int sampeSize, int blockSize) { UnencodedSubblocks = new int[blockSize]; for (int i = 0; i < blockSize; i++) UnencodedSubblocks[i] = sb.ReadBigEndianInt32(); }
////------------------------------------------------------------------------------------------------------------------------------ private static ApeHeader ReadHeader(StreamBuffer stream, TagOrigin tagOrigin) { if (stream == null) throw new ArgumentNullException("stream"); long startPosition = stream.Position; long streamLength = stream.Length; if (streamLength < ApeTag.HeaderSize) return null; // Look for a header at the current position if (tagOrigin == TagOrigin.Start) { // Look for a header at the current position long startPositionHeader = startPosition; long endPositionHeader = Math.Min(startPositionHeader + ApeTag.HeaderSize, streamLength); ApeHeader hdr = ReadHeader(stream, startPositionHeader, endPositionHeader); if (hdr != null) return hdr; // Look for a header past the current position startPositionHeader = endPositionHeader; endPositionHeader = Math.Min(startPositionHeader + ApeTag.HeaderSize, streamLength); hdr = ReadHeader(stream, startPositionHeader, endPositionHeader); if (hdr != null) return hdr; } else if (tagOrigin == TagOrigin.End) { // Look for a footer before the current position long startPositionHeader = Math.Max(startPosition - ApeTag.FooterSize, 0); long endPositionHeader = Math.Min(startPositionHeader + ApeTag.FooterSize, streamLength); ApeHeader hdr = ReadHeader(stream, startPositionHeader, endPositionHeader); if (hdr != null) return hdr; // Look for a footer before the previous start position startPositionHeader = Math.Max(startPositionHeader - ApeTag.FooterSize, 0); endPositionHeader = Math.Min(startPositionHeader + ApeTag.FooterSize, streamLength); hdr = ReadHeader(stream, startPositionHeader, endPositionHeader); if (hdr != null) return hdr; } return null; }