OggPacket RebuildIdPacket(Sample sample, uint blocksize_short, uint blocksize_long) { using (var buf = new MemoryStream()) using (var output = new BinaryWriter(buf)) { output.Write((byte)1); output.Write("vorbis".ToCharArray()); output.Write(0); output.Write((byte)sample.Channels); output.Write(sample.SampleRate); output.Write(0); output.Write(0); output.Write(0); int lo = VorbisInfo.CountBits(blocksize_short); int hi = VorbisInfo.CountBits(blocksize_long); int bits = hi << 4 | lo; output.Write((byte)bits); output.Write((byte)1); output.Flush(); var packet = new OggPacket(); packet.SetPacket(0, buf.ToArray()); packet.BoS = true; return(packet); } }
OggPacket RebuildSetupPacket(byte[] setup_packet) { var packet = new OggPacket(); packet.SetPacket(2, setup_packet); return(packet); }
OggPacket RebuildCommentPacket() { var comment = new VorbisComment(); var packet = new OggPacket(); comment.HeaderOut(packet); return(packet); }
SoundInput RebuildVorbis(Sample sample) { if (!sample.MetaData.ContainsKey(ChunkType.VorbisData)) { throw new InvalidFormatException("No VORBISDATA chunk in FSB5 Vorbis stream."); } var vorbis_data = sample.MetaData[ChunkType.VorbisData] as VorbisData; var setup_data = GetVorbisHeader(vorbis_data.Crc32); var state = new OggStreamState(1); var id_packet = RebuildIdPacket(sample, 0x100, 0x800); var comment_packet = RebuildCommentPacket(); var setup_packet = RebuildSetupPacket(setup_data); var info = CreateVorbisInfo(sample, setup_packet); var output = new MemoryStream(); state.PacketIn(id_packet); state.Write(output); state.PacketIn(comment_packet); state.Write(output); state.PacketIn(setup_packet); state.Write(output); state.Flush(output); long packet_no = setup_packet.PacketNo + 1; long granule_pos = 0; int prev_block_size = 0; using (var input = new BinMemoryStream(sample.Data)) { var packet = new OggPacket(); int packet_size = ReadPacketSize(input); while (packet_size > 0) { packet.SetPacket(packet_no++, input.ReadBytes(packet_size)); packet_size = ReadPacketSize(input); packet.EoS = 0 == packet_size; int block_size = info.PacketBlockSize(packet); if (prev_block_size != 0) { granule_pos += (block_size + prev_block_size) / 4; } else { granule_pos = 0; } packet.GranulePos = granule_pos; prev_block_size = block_size; state.PacketIn(packet); state.Write(output); } } output.Position = 0; return(new OggInput(output)); }
VorbisInfo CreateVorbisInfo(Sample sample, OggPacket setup_packet) { var info = new VorbisInfo { Channels = sample.Channels, Rate = sample.SampleRate, }; info.CodecSetup.BlockSizes[0] = 0x100; info.CodecSetup.BlockSizes[1] = 0x800; var comment = new VorbisComment { Vendor = VorbisComment.EncodeVendorString }; info.SynthesisHeaderin(comment, setup_packet); return(info); }
private void AddPacket(byte[] data, uint sampleLength, bool delayWrite) { var packet = new OggPacket(); if (data.Length >= 255) { ThrowExceptions.Custom(Exc.GetStackTrace(), type, Exc.CallingMethod(),ExtractionException("Packet exceeds maximum size."); } _granulePosition += sampleLength; packet.Data = data; packet.GranulePosition = _granulePosition; _packetList.Add(packet); _packetListDataSize += data.Length; if (!delayWrite || (_packetListDataSize >= _targetPageDataSize) || (_packetList.Count == 255)) { WritePage(); } }
private void AddPacket(byte[] data, uint sampleLength, bool delayWrite) { var packet = new OggPacket(); if (data.Length >= 255) { throw new Exception("Packet exceeds maximum size."); } _granulePosition += sampleLength; packet.Data = data; packet.GranulePosition = _granulePosition; _packetList.Add(packet); _packetListDataSize += data.Length; if (!delayWrite || _packetListDataSize >= _targetPageDataSize || _packetList.Count == 255) { WritePage(); } }
public void PacketIn(OggPacket packet) { if (packet == null) { return; } ClearReturnedBody(); var bytes = packet.PacketData.Length; var lacingValueCount = (int)(bytes / 255f + 1); // make sure we have the buffer storage ExpandBody(bytes); ExpandLacing(lacingValueCount); // Copy in the submitted packet. Array.Copy(packet.PacketData, 0, _bodyData, _bodyFill, bytes); _bodyFill += bytes; // Store lacing vals for this packet int i; for (i = 0; i < lacingValueCount - 1; i++) { _lacingValues[_lacingFill + i] = 255; _granuleValues[_lacingFill + i] = _granulePosition; } _lacingValues[_lacingFill + i] = (int)(bytes % 255f); _granulePosition = _granuleValues[_lacingFill + i] = packet.GranulePosition; // flag the first segment as the beginning of the packet _lacingValues[_lacingFill] |= 0x100; _lacingFill += lacingValueCount; if (packet.EndOfStream) { Finished = true; } }
public void Encode(OggStreamState oggStreamState, VorbisBlock block, Stream stream) { OggPacket packet = new OggPacket(); OggPage page = new OggPage(); /* vorbis does some data preanalysis, then divvies up blocks for * more involved (potentially parallel) processing. Get a single * block for encoding now */ while (BlockOut(block)) { /* analysis, assume we want to use bitrate management */ block.Analyze(); block.BitrateAddBlock(); while (BitrateFlushPacket(packet) != 0) { /* weld the packet into the bitstream */ NativeMethods.ogg_stream_packetin(ref oggStreamState.InternalStruct, ref packet.InternalStruct); /* write out pages (if any) */ bool eos = false; while (!eos) { int result = NativeMethods.ogg_stream_pageout(ref oggStreamState.InternalStruct, ref og); if (result == 0) { break; } page.Write(stream); /* this could be set above, but for illustrative purposes, I do * it here (to show that vorbis does know where the stream ends) */ if (xm.ogg_page_eos(ref page.InternalStruct) != 0) { eos = true; } } } } }
private void AddPacket(byte[] data, uint sampleLength, bool delayWrite) { var packet = new OggPacket(); if (data.Length >= 255) { throw new ExtractionException("Packet exceeds maximum size."); } _granulePosition += sampleLength; packet.Data = data; packet.GranulePosition = _granulePosition; _packetList.Add(packet); _packetListDataSize += data.Length; if (!delayWrite || (_packetListDataSize >= _targetPageDataSize) || (_packetList.Count == 255)) { WritePage(); } }
public static void WriteFile(Unity_Studio.EndianStream stream, string file, int offset, int size, Ogg ogg) { // Write to disk using (BinaryWriter writer = new BinaryWriter(File.Open(file, FileMode.Create))) { // Only support header CRC 3605052372 for now OggVorbisHeader head = new OggVorbisHeader(); HeaderPacketBuilder hpb = new HeaderPacketBuilder(); CodecSetup cSetup = new CodecSetup(null); cSetup.BlockSizes[0] = 256; cSetup.BlockSizes[1] = 2048; VorbisInfo info = new VorbisInfo(cSetup, (int)ogg.channels, (int)ogg.frequency, 0); OggPacket headerInfo = hpb.BuildInfoPacket(info); Comments comments = new Comments(); if (ogg.loopStart > 0 && ogg.loopEnd > 0) { comments.AddTag("LOOP_START", ogg.loopStart.ToString()); comments.AddTag("LOOP_END", ogg.loopEnd.ToString()); } OggPacket headerComment = hpb.BuildCommentsPacket(comments); OggPacket headerSetup = new OggPacket(OggVorbisHeader.GetHeader(ogg.crc32), false, 0, 2); OggStream output = new OggStream(1); output.PacketIn(headerInfo); output.PacketIn(headerComment); output.PacketIn(headerSetup); stream.Position = offset; UInt16 packetSize = stream.ReadUInt16(); int prevPacketNo = 2; int prevGranulePos = 0; while (packetSize > 0) { OggPacket packet = new OggPacket(stream.ReadBytes(packetSize), false, 0, prevPacketNo + 1); byte firstByte = packet.PacketData[0]; // OK for stereo int granuleSize = 128; if ((firstByte & 2) != 0) { granuleSize = 1024; } if (ogg.channels == 1) { granuleSize /= 4; } packet.GranulePosition = prevGranulePos + granuleSize; if (stream.Position + 2 < offset + size) { packetSize = stream.ReadUInt16(); } else { packetSize = 0; } packet.EndOfStream = packetSize == 0; prevGranulePos = packet.GranulePosition; prevPacketNo = packet.PacketNumber; output.PacketIn(packet); OggPage page = null; if (output.PageOut(out page, true)) { writer.Write(page.Header); writer.Write(page.Body); } } //float vorbis_quality = ((ogg.quality - 1) + (ogg.quality - 100) * 0.1f) / 99.0f; //VorbisInfo.InitVariableBitRate(ogg.channels, ogg.frequency, ogg.) //writer.Write(); writer.Close(); } }
public int BitrateFlushPacket(OggPacket packet) { return(NativeMethods.vorbis_bitrate_flushpacket(ref InternalStruct, ref packet.InternalStruct)); }
public bool PacketOut(out OggPacket packet) { packet = null; // Have we started? if (!_preExtrapolated) { return(false); } // Are we done? if (_eofFlag == -1) { return(false); } var codecSetup = _vorbisInfo.CodecSetup; // By our invariant, we have lW, W and centerW set. Search for // the next boundary so we can determine nW (the next window size) // which lets us compute the shape of the current block's window // we do an envelope search even on a single blocksize; we may still // be throwing more bits at impulses, and envelope search handles // marking impulses too. var testWindow = _centerWindow + codecSetup.BlockSizes[_currentWindow] / 4 + codecSetup.BlockSizes[1] / 2 + codecSetup.BlockSizes[0] / 4; var bp = _lookups.EnvelopeLookup.Search(_pcm, _pcmCurrent, _centerWindow, testWindow); if (bp == -1) { if (_eofFlag == 0) { return(false); // not enough data currently to search for a full int block } _nextWindow = 0; } else { _nextWindow = codecSetup.BlockSizes[0] == codecSetup.BlockSizes[1] ? 0 : bp; } var centerNext = _centerWindow + codecSetup.BlockSizes[_currentWindow] / 4 + codecSetup.BlockSizes[_nextWindow] / 4; // center of next block + next block maximum right side. var blockbound = centerNext + codecSetup.BlockSizes[_nextWindow] / 2; // Not enough data yet if (_pcmCurrent < blockbound) { return(false); } // copy the vectors; ampPtr uses the local storage in vb // ampPtr tracks 'strongest peak' for later psychoacoustics var n = codecSetup.BlockSizes[_currentWindow] / 2; _lookups.PsyGlobalLookup.DecayAmpMax(n, _vorbisInfo.SampleRate); var pcmEnd = codecSetup.BlockSizes[_currentWindow]; var pcm = new float[_pcm.Length][]; var beginWindow = _centerWindow - codecSetup.BlockSizes[_currentWindow] / 2; for (var channel = 0; channel < _pcm.Length; channel++) { pcm[channel] = new float[pcmEnd]; Array.Copy(_pcm[channel], beginWindow, pcm[channel], 0, pcm[channel].Length); } // handle eof detection: eof==0 means that we've not yet received EOF eof>0 // marks the last 'real' sample in pcm[] eof<0 'no more to do'; doesn't get here var eofFlag = false; if (_eofFlag != 0) { if (_centerWindow >= _eofFlag) { _eofFlag = -1; eofFlag = true; } } var data = PerformAnalysis(pcm, pcmEnd); packet = new OggPacket(data, eofFlag, _granulePosition, _sequence++); if (!eofFlag) { AdvanceStorageVectors(centerNext); } return(true); }