public OggBitStream(OggPacket input) { // certainly an overhead to create a new stream for every packet, but it's so convenient var buf = new MemoryStream(input.Packet); m_input = new LsbBitStream(buf); }
// https://www.xiph.org/vorbis/doc/libvorbis/vorbis_packet_blocksize.html public int PacketBlockSize(OggPacket op) { using (var input = new OggBitStream(op)) { // Check the packet type if (input.ReadBits(1) != 0) { throw new InvalidDataException("Not an audio data packet."); } int modebits = 0; for (int v = CodecSetup.Modes; v > 1; v >>= 1) { modebits++; } // read our mode and pre/post windowsize int mode = input.ReadBits(modebits); if (-1 == mode) { throw new InvalidDataException("Invalid Ogg/Vorbis packet."); } return(CodecSetup.BlockSizes[CodecSetup.ModeParam[mode].BlockFlag]); } }
public bool PacketIn(OggPacket op) { int bytes = op.Packet.Length; int lacing_vals = bytes / 255 + 1; if (BodyReturned > 0) { // advance packet data according to the body_returned pointer. // We had to keep it around to return a pointer into the buffer last call. BodyFill -= BodyReturned; if (BodyFill > 0) { Buffer.BlockCopy(BodyData, BodyReturned, BodyData, 0, BodyFill); } BodyReturned = 0; } // make sure we have the buffer storage if (!BodyExpand(bytes) || !LacingExpand(lacing_vals)) { return(false); } // Copy in the submitted packet. Buffer.BlockCopy(op.Packet, 0, BodyData, BodyFill, op.Packet.Length); BodyFill += op.Packet.Length; // Store lacing vals for this packet int i; for (i = 0; i < lacing_vals - 1; ++i) { LacingVals[LacingFill + i] = 0xFF; GranuleVals[LacingFill + i] = GranulePos; } LacingVals[LacingFill + i] = bytes % 0xFF; GranulePos = GranuleVals[LacingFill + i] = op.GranulePos; // flag the first segment as the beginning of the packet LacingVals[LacingFill] |= 0x100; LacingFill += lacing_vals; PacketNo++; EoS = op.EoS; return(true); }
// https://xiph.org/vorbis/doc/libvorbis/vorbis_synthesis_headerin.html public void SynthesisHeaderin(VorbisComment vc, OggPacket op) { using (var input = new OggBitStream(op)) { int packtype = input.ReadUInt8(); var buf = input.ReadBytes(6); if (!buf.AsciiEqual("vorbis")) { throw new InvalidDataException("Not an Ogg/Vorbis stream."); } switch (packtype) { case 1: if (!op.BoS) { throw InvalidHeader(); } if (Rate != 0) { throw InvalidHeader(); } UnpackInfo(input); break; case 3: if (0 == Rate) { throw InvalidHeader(); } vc.UnpackComment(input); break; case 5: if (0 == Rate || null == vc.Vendor) { throw InvalidHeader(); } UnpackBooks(input); break; default: throw InvalidHeader(); } } }
// https://xiph.org/vorbis/doc/libvorbis/vorbis_commentheader_out.html public void HeaderOut(OggPacket packet) { using (var buf = new MemoryStream()) using (var output = new BinaryWriter(buf)) { // preamble output.Write((byte)3); output.Write("vorbis".ToCharArray()); // vendor output.Write(EncodeVendorString.Length); output.Write(EncodeVendorString); // comments output.Write(Comments.Count); foreach (var comment in Comments) { if (comment != null && comment.Length > 0) { output.Write(comment.Length); output.Write(comment); } else { output.Write(0); } } output.Write((byte)1); output.Flush(); packet.SetPacket(1, buf.ToArray()); packet.BoS = false; packet.EoS = false; packet.GranulePos = 0; } }