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); } }
public Sound LoadOgg(string fileName) { var stream = new OggVorbisFileStream(fileName); VorbisInfo vInfo = stream.Info; WaveFormatExtensible wfe = new WaveFormatExtensible { // cbSize BitsPerSample = 16, Channels = (short)vInfo.Channels, SamplesPerSecond = vInfo.Rate, // ogg vorbis always uses 16 bits AverageBytesPerSecond = vInfo.Rate * vInfo.Channels * 2, BlockAlignment = (short)(2 * vInfo.Channels), FormatTag = WaveFormatTag.Pcm }; AudioBuffer buffer = new AudioBuffer(); buffer.AudioData = stream; buffer.AudioBytes = (int)stream.Length; buffer.Flags = BufferFlags.EndOfStream; return(new Sound { Buffer = buffer, Stream = stream, Format = wfe, Program = this }); }
private static void InitOggStream(int sampleRate, int channels, out OggStream oggStream, out ProcessingState processingState) { // Stores all the static vorbis bitstream settings var info = VorbisInfo.InitVariableBitRate(channels, sampleRate, 0.5f); // set up our packet->stream encoder var serial = new Random().Next(); oggStream = new OggStream(serial); // ========================================================= // HEADER // ========================================================= // Vorbis streams begin with three headers; the initial header (with // most of the codec setup parameters) which is mandated by the Ogg // bitstream spec. The second header holds any comment fields. The // third header holds the bitstream codebook. var comments = new Comments(); comments.AddTag("ARTIST", "TTS"); var infoPacket = HeaderPacketBuilder.BuildInfoPacket(info); var commentsPacket = HeaderPacketBuilder.BuildCommentsPacket(comments); var booksPacket = HeaderPacketBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); // ========================================================= // BODY (Audio Data) // ========================================================= processingState = ProcessingState.Create(info); }
public void Convert(string inputFile, string outputFile) { using (var outputStream = File.Create(outputFile)) { var channels = AudioSampleReader.ReadChannels(inputFile, out var waveFormat); var oggStream = new OggStream(StaticRandom.Rng.Next()); // Build header var headerBuilder = new HeaderPacketBuilder(); var audioInfo = VorbisInfo.InitVariableBitRate(channels.Count, waveFormat.SampleRate, 0.1f); var infoPacket = headerBuilder.BuildInfoPacket(audioInfo); var commentsPacket = headerBuilder.BuildCommentsPacket(new Comments()); var booksPacket = headerBuilder.BuildBooksPacket(audioInfo); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); WriteHeader(oggStream, outputStream); // Store audio var processingState = ProcessingState.Create(audioInfo); var normalizedChannels = Normalize(channels); processingState.WriteData(normalizedChannels, normalizedChannels[0].Length); processingState.WriteEndOfStream(); WriteAudio(oggStream, outputStream, processingState); } }
public EnvelopeLookup(PsyGlobal psyGlobal, VorbisInfo info) { _psyGlobal = psyGlobal; var codecSetup = info.CodecSetup; _minEnergy = codecSetup.PsyGlobalParam.PreEchoMinEnergy; _cursor = codecSetup.BlockSizes[1] / 2; _mdctWindow = new float[WindowLength]; _mdctLookup = new MdctLookup(WindowLength); for (var i = 0; i < _mdctWindow.Length; i++) { _mdctWindow[i] = (float)Math.Sin(i / (WindowLength - 1.0) * Math.PI); _mdctWindow[i] *= _mdctWindow[i]; } _bands = new EnvelopeBand[PsyGlobal.EnvelopeBands]; // Magic follows _bands[0] = new EnvelopeBand(2, 4); _bands[1] = new EnvelopeBand(4, 5); _bands[2] = new EnvelopeBand(6, 6); _bands[3] = new EnvelopeBand(9, 8); _bands[4] = new EnvelopeBand(13, 8); _bands[5] = new EnvelopeBand(17, 8); _bands[6] = new EnvelopeBand(22, 8); _filters = Enumerable .Range(0, PsyGlobal.EnvelopeBands * info.Channels) .Select(s => new EnvelopeFilterState()) .ToArray(); _mark = new int[WindowLength]; }
/// <summary> /// VorbisFileWriter that actually writes to a stream /// </summary> /// <param name="outStream">Stream to be written to</param> /// <param name="sampleRate">The sample rate to use</param> /// <param name="channels">The number of channels to use</param> /// <param name="quality">The base quality for Vorbis encoding</param> public VorbisFileWriter(Stream outStream, int sampleRate, int channels, float quality = 0.5f) { this.outStream = outStream; SampleRate = sampleRate; Channels = channels; if (!startBuffers.ContainsKey(sampleRate)) { throw new InvalidOperationException($"Vorbis writer does not support {sampleRate} sample rate."); } // Stores all the static vorbis bitstream settings Console.WriteLine($"Initiating variable bit rate: {channels} channels, {sampleRate} sample rate, {quality} quality"); var info = VorbisInfo.InitVariableBitRate(channels, sampleRate, quality); // set up our packet->stream encoder var serial = MainWindow.MainRandom.Next(); oggStream = new OggStream(serial); // ========================================================= // HEADER // ========================================================= // Vorbis streams begin with three headers; the initial header (with // most of the codec setup parameters) which is mandated by the Ogg // bitstream spec. The second header holds any comment fields. The // third header holds the bitstream codebook. var headerBuilder = new HeaderPacketBuilder(); var comments = new Comments(); var infoPacket = headerBuilder.BuildInfoPacket(info); var commentsPacket = headerBuilder.BuildCommentsPacket(comments); var booksPacket = headerBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); // Flush to force audio data onto its own page per the spec FlushPages(oggStream, outStream, true); // ========================================================= // BODY (Audio Data) // ========================================================= processingState = ProcessingState.Create(info); // Append some zeros at the start so the result has the same length as the input int bufferSize = startBuffers[sampleRate]; float[][] outSamples = new float[channels][]; for (int ch = 0; ch < channels; ch++) { outSamples[ch] = new float[bufferSize]; } processingState.WriteData(outSamples, bufferSize); }
public static OggPacket BuildBooksPacket(VorbisInfo info) { var buffer = new EncodeBuffer(4096); PackBooks(buffer, info); var bytes = buffer.GetBytes(); return(new OggPacket(bytes, false, 0, 2)); }
public static OggPacket BuildInfoPacket(VorbisInfo info) { var buffer = new EncodeBuffer(); PackInfo(buffer, info); var bytes = buffer.GetBytes(); return(new OggPacket(bytes, false, 0, 0)); }
private static void PackMapping(EncodeBuffer buffer, VorbisInfo info, Mapping mapping) { /* another 'we meant to do it this way' hack... up to beta 4, we * packed 4 binary zeros here to signify one submapping in use. We * now redefine that to mean four bitflags that indicate use of * deeper features; bit0:submappings, bit1:coupling, * bit2,3:reserved. This is backward compatible with all actual uses * of the beta code. */ if (mapping.SubMaps > 1) { buffer.Write(1, 1); buffer.Write((uint)mapping.SubMaps - 1, 4); } else { buffer.Write(0, 1); } if (mapping.CouplingSteps > 0) { buffer.Write(1, 1); buffer.Write((uint)mapping.CouplingSteps - 1, 8); var couplingBits = Encoding.Log(info.Channels - 1); for (var i = 0; i < mapping.CouplingSteps; i++) { buffer.Write((uint)mapping.CouplingMag[i], couplingBits); buffer.Write((uint)mapping.CouplingAng[i], couplingBits); } } else { buffer.Write(0, 1); } buffer.Write(0, 2); // 2,3:reserved // we don't write the channel submappings if we only have one... if (mapping.SubMaps > 1) { for (var i = 0; i < info.Channels; i++) { buffer.Write((uint)mapping.ChannelMuxList[i], 4); } } for (var i = 0; i < mapping.SubMaps; i++) { buffer.Write(0, 8); // time submap unused buffer.Write((uint)mapping.FloorSubMap[i], 8); buffer.Write((uint)mapping.ResidueSubMap[i], 8); } }
private int _sequence = 3; // compressed audio packets start after the headers with sequence number 3 private ProcessingState( VorbisInfo vorbisInfo, LookupCollection lookups, float[][] pcm, int[] window, int centerWindow) { _vorbisInfo = vorbisInfo; _lookups = lookups; _pcm = pcm; _window = window; _centerWindow = centerWindow; }
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 static void PackBooks(EncodeBuffer buffer, VorbisInfo info) { var codecSetup = info.CodecSetup; buffer.Write(0x05, 8); buffer.WriteString(VorbisString); buffer.Write((uint)(codecSetup.BookParams.Count - 1), 8); foreach (var book in codecSetup.BookParams) { PackStaticBook(buffer, book); } // times; hook placeholders buffer.Write(0, 6); buffer.Write(0, 16); buffer.Write((uint)(codecSetup.FloorParams.Count - 1), 6); foreach (var floor in codecSetup.FloorParams) { buffer.Write(1, 16); // For now we're only using floor type 1 PackFloor(buffer, floor); } buffer.Write((uint)(codecSetup.ResidueParams.Count - 1), 6); foreach (var residue in codecSetup.ResidueParams) { buffer.Write((uint)residue.ResidueType, 16); PackResidue(buffer, residue); } buffer.Write((uint)(codecSetup.MapParams.Count - 1), 6); foreach (var mapping in codecSetup.MapParams) { buffer.Write(0, 16); // Mapping type is always zero PackMapping(buffer, info, mapping); } buffer.Write((uint)(codecSetup.ModeParams.Count - 1), 6); for (var i = 0; i < codecSetup.ModeParams.Count; i++) { PackModes(buffer, codecSetup, i); } buffer.Write(1, 1); }
private static void PackInfo(EncodeBuffer buffer, VorbisInfo info) { var codecSetup = info.CodecSetup; // preamble buffer.Write(0x01, 8); buffer.WriteString(VorbisString); // basic information about the stream buffer.Write(0x00, 32); buffer.Write((uint)info.Channels, 8); buffer.Write((uint)info.SampleRate, 32); buffer.Write(0, 32); // Bit rate upper not used buffer.Write((uint)info.BitRateNominal, 32); buffer.Write(0, 32); // Bit rate lower not used buffer.Write((uint)Encoding.Log(codecSetup.BlockSizes[0] - 1), 4); buffer.Write((uint)Encoding.Log(codecSetup.BlockSizes[1] - 1), 4); buffer.Write(1, 1); }
public static ProcessingState Create(VorbisInfo info) { if (info == null) { throw new ArgumentNullException(nameof(info)); } var codecSetup = info.CodecSetup; // initialize the storage vectors. blocksize[1] is small for encode, but the correct size for decode var pcmStorage = codecSetup.BlockSizes[1]; var pcm = new float[info.Channels][]; for (var i = 0; i < pcm.Length; i++) { pcm[i] = new float[pcmStorage]; } // Vorbis I uses only window type 0 var window = new int[2]; window[0] = Encoding.Log(codecSetup.BlockSizes[0]) - 7; window[1] = Encoding.Log(codecSetup.BlockSizes[1]) - 7; var centerWindow = codecSetup.BlockSizes[1] / 2; var lookups = LookupCollection.Create(info); return(new ProcessingState( info, lookups, pcm, window, centerWindow)); }
private void process() { lock (lockObject) preparing = true; byte[] outBuffer = new Byte[4096]; if (byteStream == null) { oggFile = new OggVorbisFileStream(fileNames[playPointer]); } else { oggStream = new OggVorbisEncodedStream(byteStream); } MemoryStream PcmStream = null; int PcmBytes = -1; PcmStream = new MemoryStream(); WaveFormat waveFormat = new WaveFormat(); AudioBuffer[] theBuffers = new AudioBuffer[maxBuffers]; int nextBuffer = 0; bool firstLoop = true; bool startedSourceVoice = false; // Decode the Ogg Vorbis data into its PCM data while (PcmBytes != 0) { // Get the next chunk of PCM data, pin these so the GC can't while (true) { PcmBytes = (oggStream == null) ? oggFile.Read(outBuffer, 0, outBuffer.Length) : oggStream.Read(outBuffer, 0, outBuffer.Length); if (PcmBytes == 0) //Reached the end { break; } PcmStream.Flush(); PcmStream.Position = 0; PcmStream.Write(outBuffer, 0, PcmBytes); PcmStream.Position = 0; if (theBuffers[nextBuffer] != null) { theBuffers[nextBuffer].Stream.Dispose(); theBuffers[nextBuffer] = null; } theBuffers[nextBuffer] = new AudioBuffer(SharpDX.DataStream.Create <byte>(PcmStream.ToArray(), true, false)); theBuffers[nextBuffer].AudioBytes = PcmBytes; theBuffers[nextBuffer].LoopCount = 0; if (firstLoop) { VorbisInfo info = (oggStream == null) ? oggFile.Info : oggStream.Info; //BlockAlign = info.Channels * (bitsPerSample / 8); //AverageBytesPerSecond = info.Rate * BlockAlign; //waveFormat.AverageBytesPerSecond = AverageBytesPerSecond; //waveFormat.BitsPerSample = (short)bitsPerSample; //waveFormat.BlockAlignment = (short)BlockAlign; //waveFormat.Channels = (short)info.Channels; //waveFormat.SamplesPerSecond = info.Rate; waveFormat = new WaveFormat(info.Rate, bitsPerSample, info.Channels); //waveFormat.Encoding= WaveFormatEncoding.Pcm; sourceVoice = new SourceVoice(device, waveFormat); sourceVoice.SetVolume(volume); } //if first time looping, create sourcevoice sourceVoice.SubmitSourceBuffer(theBuffers[nextBuffer], null); if (nextBuffer == theBuffers.Length - 1) { nextBuffer = 0; } else { nextBuffer++; } //If we're done filling the buffer for the first time if (!startedSourceVoice && sourceVoice.State.BuffersQueued == maxBuffers) { sourceVoice.Start(); startedSourceVoice = true; lock (lockObject) { playing = true; preparing = false; } //lock } firstLoop = false; if (startedSourceVoice) { while (sourceVoice.State.BuffersQueued > maxBuffers - 1) { if (stopNow) { break; } Thread.Sleep(5); } } //if started source voice if (stopNow) { break; } } //while if (stopNow) { break; } //We don't have any more data but file could still be playing the remaining data. if (PcmBytes == 0 /*&& !loop*/) { if (!stopNow) { while (sourceVoice.State.BuffersQueued > 0 && !stopNow) { Thread.Sleep(10); } } //if doesn't want to stop ogg if (!loop) { break; //exit the loop since we ran out of data and don't want to loop back } } //if we ran out of data if (PcmBytes == 0 && loop) { PcmBytes = -1; if (oggFile != null) { oggFile.Position = 0; } if (oggStream != null) { oggStream.Position = 0; } } //if we ran out of data but want to loop back } //while more data //Done playing, or file requested stop, //so clean up and tell calling thread that //buffer has stopped and cleaned up. //calling thread doesn't know buffer has stopped until we clean things up //so we don't lose memory //Clean up the resources if (sourceVoice != null) { sourceVoice.ExitLoop(); //stop looping if looping sourceVoice.Stop(); } sourceVoice.Dispose(); sourceVoice = null; if (oggFile != null) { oggFile.Close(); oggFile = null; } outBuffer = null; for (int i = 0; i < theBuffers.Length; i++) { if (theBuffers[i] != null) { theBuffers[i].Stream.Dispose(); theBuffers[i] = null; } } theBuffers = null; if (oggStream != null) { oggStream.Close(); oggStream = null; } PcmStream.Dispose(); PcmStream = null; if (stopEvent != null) { stopEvent(); } } //method
private void process(bool initializeNextTrack) { preparing = true; SecondarySoundBuffer sBuff = null; int p = playPointer; if (initializeNextTrack) { p++; // Point to the next track which we will initialize. } MemoryStream PcmStream = null; PlayFlags f = PlayFlags.None; if (p > soundBuffers.Count - 1) { SoundBufferDescription desc = new SoundBufferDescription(); desc.Flags = BufferFlags.ControlPositionNotify | BufferFlags.ControlVolume | BufferFlags.GetCurrentPosition2 | BufferFlags.GlobalFocus; byte[] outBuffer = new Byte[4096]; oggFile = new OggVorbisFileStream(fileNames[p]); PcmStream = new MemoryStream(); int PcmBytes = -1; WaveFormat waveFormat = new WaveFormat(); // Decode the Ogg Vorbis data into its PCM data while (PcmBytes != 0) { PcmBytes = oggFile.Read(outBuffer, 0, outBuffer.Length); PcmStream.Write(outBuffer, 0, PcmBytes); } VorbisInfo info = oggFile.Info; waveFormat = new WaveFormat(info.Rate, bitsPerSample, info.Channels); desc.Format = waveFormat; desc.BufferBytes = (int)PcmStream.Length; lock (lockObject) // So we don't lose a simultaneous volume change. soundBuffers.Add(sBuff = new SecondarySoundBuffer(device, desc)); sBuff.Write(PcmStream.ToArray(), 0, LockFlags.EntireBuffer); // In a multi-wave playback, only loop the last track. The preceeding tracks are intros. // Next, if we have a multi-file situation, we need to wait for the current file to stop playing before starting the next one. // This handler will also fire when a sound is done playing by default so we can explicitly dispose of the soundBuffer. stoppedSignal = new AutoResetEvent(false); NotificationPosition[] n = { new NotificationPosition() { Offset = (int)PcmStream.Length - 1, WaitHandle = new AutoResetEvent(false) } }; stoppedSignal = (AutoResetEvent)(n[0].WaitHandle); sBuff.SetNotificationPositions(n); } else // If this buffer has already been initialized ahead of time { sBuff = soundBuffers[p]; } if (!initializeNextTrack) { Thread t = new Thread(stopEventHandler); t.Start(); sBuff.Volume = m_volume; f = (loop && p == fileNames.Length - 1) ? PlayFlags.Looping : PlayFlags.None; sBuff.Play(0, f); } if (PcmStream != null) { oggFile.Close(); oggFile.Dispose(); PcmStream.Close(); PcmStream.Dispose(); } if (!initializeNextTrack && playPointer < fileNames.Length - 1) // Prepare the next track. { process(true); } preparing = false; }
private static void Main() { var stdin = new FileStream(@"unencoded.raw", FileMode.Open, FileAccess.Read); var stdout = new FileStream(@"encoded.ogg", FileMode.Create, FileAccess.Write); // StripWavHeader(stdin); // Stores all the static vorbis bitstream settings var info = VorbisInfo.InitVariableBitRate(2, 44100, 0.1f); // set up our packet->stream encoder var serial = new Random().Next(); var oggStream = new OggStream(serial); // ========================================================= // HEADER // ========================================================= // Vorbis streams begin with three headers; the initial header (with // most of the codec setup parameters) which is mandated by the Ogg // bitstream spec. The second header holds any comment fields. The // third header holds the bitstream codebook. var headerBuilder = new HeaderPacketBuilder(); var comments = new Comments(); comments.AddTag("ARTIST", "TEST"); var infoPacket = headerBuilder.BuildInfoPacket(info); var commentsPacket = headerBuilder.BuildCommentsPacket(comments); var booksPacket = headerBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); // Flush to force audio data onto its own page per the spec OggPage page; while (oggStream.PageOut(out page, true)) { stdout.Write(page.Header, 0, page.Header.Length); stdout.Write(page.Body, 0, page.Body.Length); } // ========================================================= // BODY (Audio Data) // ========================================================= var processingState = ProcessingState.Create(info); var buffer = new float[info.Channels][]; buffer[0] = new float[SampleSize]; buffer[1] = new float[SampleSize]; var readbuffer = new byte[SampleSize * 4]; while (!oggStream.Finished) { var bytes = stdin.Read(readbuffer, 0, readbuffer.Length); if (bytes == 0) { processingState.WriteEndOfStream(); } else { var samples = bytes / 4; for (var i = 0; i < samples; i++) { // uninterleave samples buffer[0][i] = (short)((readbuffer[i * 4 + 1] << 8) | (0x00ff & readbuffer[i * 4])) / 32768f; buffer[1][i] = (short)((readbuffer[i * 4 + 3] << 8) | (0x00ff & readbuffer[i * 4 + 2])) / 32768f; } processingState.WriteData(buffer, samples); } OggPacket packet; while (!oggStream.Finished && processingState.PacketOut(out packet)) { oggStream.PacketIn(packet); while (!oggStream.Finished && oggStream.PageOut(out page, false)) { stdout.Write(page.Header, 0, page.Header.Length); stdout.Write(page.Body, 0, page.Body.Length); } } } stdin.Close(); stdout.Close(); }
// OGG-Conversion private void OGGConversion() { progBarVisible = true; try { FileStream stdin; FileStream stdout; if (!ConvUsespreset) { stdin = new FileStream(ConvTitle + ".wav", FileMode.Open, FileAccess.Read); stdout = new FileStream(ConvTitle + ".ogg", FileMode.Create, FileAccess.Write); } else { stdin = new FileStream(Filepath + "\\" + ConvTitle + ".wav", FileMode.Open, FileAccess.Read); stdout = new FileStream(Filepath + "\\" + ConvTitle + ".ogg", FileMode.Create, FileAccess.Write); } var info = VorbisInfo.InitVariableBitRate(2, 48000, 0.1f); var serial = new Random().Next(); var oggStream = new OggStream(serial); var headerBuilder = new HeaderPacketBuilder(); var comments = new Comments(); comments.AddTag("ARTIST", ""); var infoPacket = headerBuilder.BuildInfoPacket(info); var commentsPacket = headerBuilder.BuildCommentsPacket(comments); var booksPacket = headerBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); OggPage page; while (oggStream.PageOut(out page, true)) { stdout.Write(page.Header, 0, page.Header.Length); stdout.Write(page.Body, 0, page.Body.Length); } var processingState = ProcessingState.Create(info); var buffer = new float[info.Channels][]; buffer[0] = new float[SampleSize]; buffer[1] = new float[SampleSize]; var readbuffer = new byte[SampleSize * 4]; while (!oggStream.Finished) { var bytes = stdin.Read(readbuffer, 0, readbuffer.Length); if (bytes == 0) { processingState.WriteEndOfStream(); } else { var samples = bytes / 4; progBarMax = samples; progBarWEE = false; for (var i = 0; i < samples; i++) { // uninterleave samples buffer[0][i] = (short)((readbuffer[i * 4 + 1] << 8) | (0x00ff & readbuffer[i * 4])) / 32768f; buffer[1][i] = (short)((readbuffer[i * 4 + 3] << 8) | (0x00ff & readbuffer[i * 4 + 2])) / 32768f; progBarValue = i; } progBarWEE = true; processingState.WriteData(buffer, samples); } OggPacket packet; while (!oggStream.Finished && processingState.PacketOut(out packet)) { oggStream.PacketIn(packet); while (!oggStream.Finished && oggStream.PageOut(out page, false)) { stdout.Write(page.Header, 0, page.Header.Length); stdout.Write(page.Body, 0, page.Body.Length); } } } stdin.Close(); stdout.Close(); if (!ConvUsespreset) { File.Delete(ConvTitle + ".wav"); } else { File.Delete(Filepath + "\\" + ConvTitle + ".wav"); } } catch (Exception error) { errortext = Convert.ToString(error); } progBarVisible = false; Thread.CurrentThread.Abort(); }
//public uint crc32; //public int blocksize_short; //public int blocksize_long; //public uint setup_header_size; //public char[] setup_header; public Header(int channels, int rate, int quality) { float vorbis_quality = ((quality - 1) + (quality - 100) * 0.1f) / 99.0f; VorbisInfo info = VorbisInfo.InitVariableBitRate(channels, rate, vorbis_quality); // missing OV_ECTL_COUPLING_SET to 1, is this needed? }
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 static LookupCollection Create(VorbisInfo info) { var codecSetup = info.CodecSetup; var psyGlobal = new PsyGlobalLookup(codecSetup.PsyGlobalParam); var envelope = new EnvelopeLookup(codecSetup.PsyGlobalParam, info); // MDCT is tranform 0 var transform = new MdctLookup[2]; transform[0] = new MdctLookup(codecSetup.BlockSizes[0]); transform[1] = new MdctLookup(codecSetup.BlockSizes[1]); // analysis always needs an fft var fftLookup = new DrftLookup[2]; fftLookup[0] = new DrftLookup(codecSetup.BlockSizes[0]); fftLookup[1] = new DrftLookup(codecSetup.BlockSizes[1]); // finish the codebooks if (codecSetup.FullBooks == null) { codecSetup.FullBooks = new CodeBook[codecSetup.BookParams.Count]; for (var i = 0; i < codecSetup.BookParams.Count; i++) { codecSetup.FullBooks[i] = CodeBook.InitEncode(codecSetup.BookParams[i]); } } var psyLookup = new PsyLookup[codecSetup.PsyParams.Count]; for (var i = 0; i < psyLookup.Length; i++) { psyLookup[i] = new PsyLookup( codecSetup.PsyParams[i], codecSetup.PsyGlobalParam, codecSetup.BlockSizes[codecSetup.PsyParams[i].BlockFlag] / 2, info.SampleRate); } // initialize all the backend lookups var floor = new FloorLookup[codecSetup.FloorParams.Count]; for (var i = 0; i < floor.Length; i++) { floor[i] = new FloorLookup(codecSetup.FloorParams[i]); } var residue = new ResidueLookup[codecSetup.ResidueParams.Count]; for (var i = 0; i < residue.Length; i++) { residue[i] = new ResidueLookup(codecSetup.ResidueParams[i], codecSetup.FullBooks); } return(new LookupCollection( envelope, transform, psyGlobal, psyLookup, fftLookup, floor, residue)); }
public byte[] ConvertWaveBytes(byte[] waveBytes) { // Stores all the static vorbis bitstream settings VorbisInfo info = VorbisInfo.InitVariableBitRate(2, 44100, 0.1f); // set up our packet->stream encoder int serial = new Random().Next(); OggStream oggStream = new OggStream(serial); MemoryStream streamIn = new MemoryStream(waveBytes); MemoryStream streamOut = new MemoryStream(); // Vorbis streams begin with three headers; the initial header (with // most of the codec setup parameters) which is mandated by the Ogg // bitstream spec. The second header holds any comment fields. The // third header holds the bitstream codebook. var headerBuilder = new HeaderPacketBuilder(); var comments = new Comments(); var infoPacket = headerBuilder.BuildInfoPacket(info); var commentsPacket = headerBuilder.BuildCommentsPacket(comments); var booksPacket = headerBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); // Flush to force audio data onto its own page per the spec OggPage page; while (oggStream.PageOut(out page, true)) { streamOut.Write(page.Header, 0, page.Header.Length); streamOut.Write(page.Body, 0, page.Body.Length); } var processingState = ProcessingState.Create(info); var buffer = new float[info.Channels][]; buffer[0] = new float[SampleSize]; buffer[1] = new float[SampleSize]; var readbuffer = new byte[SampleSize]; while (!oggStream.Finished) { int bytes = streamIn.Read(readbuffer, 0, readbuffer.Length); if (bytes == 0) { processingState.WriteEndOfStream(); } else { var samples = bytes; for (var i = 1; i < samples; i += 2) { buffer[0][i] = (short)((readbuffer[i] << 8) | (0x00ff & readbuffer[i - 1])) / 32768f; buffer[1][i] = buffer[0][i]; } processingState.WriteData(buffer, bytes); } while (!oggStream.Finished && processingState.PacketOut(out OggPacket packet)) { oggStream.PacketIn(packet); while (!oggStream.Finished && oggStream.PageOut(out page, false)) { streamOut.Write(page.Header, 0, page.Header.Length); streamOut.Write(page.Body, 0, page.Body.Length); } } } byte[] oggBytes = streamOut.ToArray(); streamIn.Close(); streamOut.Close(); return(oggBytes); }
public static string ConvertMp3toOgg(string mp3Path, string outputDir) { var oggName = Path.GetFileNameWithoutExtension(mp3Path) + ".ogg"; try { using (var mp3 = new Mp3FileReader(mp3Path)) using (var wav = WaveFormatConversionStream.CreatePcmStream(mp3)) using (var ogg = new FileStream(Path.Combine(outputDir, oggName), FileMode.Create, FileAccess.Write)) { const int SampleSize = 4096; // Here's a reference for the code below: // https://github.com/SteveLillis/.NET-Ogg-Vorbis-Encoder/blob/master/OggVorbisEncoder.Example/Encoder.cs var info = VorbisInfo.InitVariableBitRate(2, wav.WaveFormat.SampleRate, 0.5f); // set up our packet->stream encoder var serial = new Random().Next(); var oggStream = new OggStream(serial); // ========================================================= // HEADER // ========================================================= // Vorbis streams begin with three headers; the initial header (with // most of the codec setup parameters) which is mandated by the Ogg // bitstream spec. The second header holds any comment fields. The // third header holds the bitstream codebook. var comments = new Comments(); // comments.AddTag("ARTIST", "TEST"); var infoPacket = HeaderPacketBuilder.BuildInfoPacket(info); var commentsPacket = HeaderPacketBuilder.BuildCommentsPacket(comments); var booksPacket = HeaderPacketBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); // Flush to force audio data onto its own page per the spec OggPage page; while (oggStream.PageOut(out page, true)) { ogg.Write(page.Header, 0, page.Header.Length); ogg.Write(page.Body, 0, page.Body.Length); } // ========================================================= // BODY (Audio Data) // ========================================================= var processingState = ProcessingState.Create(info); var buffer = new float[info.Channels][]; buffer[0] = new float[SampleSize]; buffer[1] = new float[SampleSize]; var readbuffer = new byte[SampleSize * 4]; while (!oggStream.Finished) { var bytes = wav.Read(readbuffer, 0, readbuffer.Length); if (bytes == 0) { processingState.WriteEndOfStream(); } else { var samples = bytes / 4; for (var i = 0; i < samples; i++) { // uninterleave samples buffer[0][i] = (short)((readbuffer[i * 4 + 1] << 8) | (0x00ff & readbuffer[i * 4])) / 32768f; buffer[1][i] = (short)((readbuffer[i * 4 + 3] << 8) | (0x00ff & readbuffer[i * 4 + 2])) / 32768f; } processingState.WriteData(buffer, samples); } while (!oggStream.Finished && processingState.PacketOut(out OggPacket packet)) { oggStream.PacketIn(packet); while (!oggStream.Finished && oggStream.PageOut(out page, false)) { ogg.Write(page.Header, 0, page.Header.Length); ogg.Write(page.Body, 0, page.Body.Length); } } } } } catch (NAudio.MmException e) { Console.WriteLine(e); // Just retry return(ConvertMp3toOgg(mp3Path, outputDir)); } catch (InvalidOperationException e) { Console.WriteLine(e); Console.WriteLine("Error while converting to " + oggName); return(oggName); } return(oggName); }
private static byte[] GenerateFile(float[][] floatSamples, int sampleRate, int channels) { using MemoryStream outputData = new MemoryStream(); // Stores all the static vorbis bitstream settings var info = VorbisInfo.InitVariableBitRate(channels, sampleRate, 0.5f); // set up our packet->stream encoder var serial = new Random().Next(); var oggStream = new OggStream(serial); // ========================================================= // HEADER // ========================================================= // Vorbis streams begin with three headers; the initial header (with // most of the codec setup parameters) which is mandated by the Ogg // bitstream spec. The second header holds any comment fields. The // third header holds the bitstream codebook. var comments = new Comments(); comments.AddTag("ARTIST", "TEST"); var infoPacket = HeaderPacketBuilder.BuildInfoPacket(info); var commentsPacket = HeaderPacketBuilder.BuildCommentsPacket(comments); var booksPacket = HeaderPacketBuilder.BuildBooksPacket(info); oggStream.PacketIn(infoPacket); oggStream.PacketIn(commentsPacket); oggStream.PacketIn(booksPacket); // Flush to force audio data onto its own page per the spec FlushPages(oggStream, outputData, true); // ========================================================= // BODY (Audio Data) // ========================================================= var processingState = ProcessingState.Create(info); for (int readIndex = 0; readIndex <= floatSamples[0].Length; readIndex += WriteBufferSize) { if (readIndex == floatSamples[0].Length) { processingState.WriteEndOfStream(); } else { processingState.WriteData(floatSamples, WriteBufferSize, readIndex); } while (!oggStream.Finished && processingState.PacketOut(out OggPacket packet)) { oggStream.PacketIn(packet); FlushPages(oggStream, outputData, false); } } FlushPages(oggStream, outputData, true); return(outputData.ToArray()); }
private void process64() { byte[] outBuffer = null; MemoryStream PcmStream = null; int PcmBytes = 0; WaveFormat waveFormat; AudioBuffer[] theBuffers = null; int nextBuffer = 0; bool firstLoop = false; bool startedSourceVoice = false; while (true) { //This is the outer loop //which controls looping in //64-bit ogg decoding. lock (lockObject) preparing = true; outBuffer = new Byte[4096]; if (byteStream == null) { oggFile = new OggVorbisFileStream(fileNames[playPointer]); } else { oggStream = new OggVorbisEncodedStream(byteStream); } PcmBytes = -1; //AverageBytesPerSecond = 0; //BlockAlign = 0; PcmStream = new MemoryStream(); waveFormat = new WaveFormat(); theBuffers = new AudioBuffer[maxBuffers]; nextBuffer = 0; firstLoop = true; startedSourceVoice = false; // Decode the Ogg Vorbis data into its PCM data while (PcmBytes != 0) { // Get the next chunk of PCM data, pin these so the GC can't while (true) { PcmBytes = (oggStream == null) ? oggFile.Read(outBuffer, 0, outBuffer.Length) : oggStream.Read(outBuffer, 0, outBuffer.Length); if (PcmBytes == 0) //Reached the end { break; } PcmStream.Flush(); PcmStream.Position = 0; PcmStream.Write(outBuffer, 0, PcmBytes); PcmStream.Position = 0; if (theBuffers[nextBuffer] != null) { theBuffers[nextBuffer].Stream.Dispose(); theBuffers[nextBuffer] = null; } theBuffers[nextBuffer] = new AudioBuffer(SharpDX.DataStream.Create <byte>(PcmStream.ToArray(), true, true)); theBuffers[nextBuffer].AudioBytes = PcmBytes; theBuffers[nextBuffer].LoopCount = 0; if (firstLoop) { VorbisInfo info = (oggStream == null) ? oggFile.Info : oggStream.Info; //BlockAlign = info.Channels * (bitsPerSample / 8); //AverageBytesPerSecond = info.Rate * BlockAlign; //waveFormat.AverageBytesPerSecond = AverageBytesPerSecond; //waveFormat.BitsPerSample = (short)bitsPerSample; //waveFormat.BlockAlignment = (short)BlockAlign; //waveFormat.Channels = (short)info.Channels; //waveFormat.SamplesPerSecond = info.Rate; waveFormat = new WaveFormat(info.Rate, bitsPerSample, info.Channels); //waveFormat.Encoding= WaveFormatEncoding.Pcm; sourceVoice = new SourceVoice(device, waveFormat); sourceVoice.SetVolume(volume); } //if first time looping, create sourcevoice sourceVoice.SubmitSourceBuffer(theBuffers[nextBuffer], null); if (nextBuffer == theBuffers.Length - 1) { nextBuffer = 0; } else { nextBuffer++; } //If we're done filling the buffer for the first time if (!startedSourceVoice && sourceVoice.State.BuffersQueued == maxBuffers) { sourceVoice.Start(); startedSourceVoice = true; lock (lockObject) { playing = true; preparing = false; } //lock } firstLoop = false; if (startedSourceVoice) { while (sourceVoice.State.BuffersQueued > maxBuffers - 1) { if (stopNow) { break; } Thread.Sleep(5); } } //if started source voice if (stopNow) { break; } } //while if (stopNow) { break; } //We don't have any more data but file could still be playing the remaining data. if (PcmBytes == 0 /*&& !loop*/) { if (!stopNow) { while (sourceVoice.State.BuffersQueued > 0 && !stopNow) { Thread.Sleep(10); } } //if doesn't want to stop ogg break; //exit the loop since we ran out of data and don't want to loop back } //if we ran out of data } //while more data //Clean everything up for another loop. //Must do clean up here since in 64-bit implementation, //we need to recreate all the objects. if (sourceVoice != null) { sourceVoice.ExitLoop(); //stop looping if looping sourceVoice.Stop(); } sourceVoice.Dispose(); sourceVoice = null; if (oggFile != null) { oggFile.Close(); oggFile = null; } outBuffer = null; for (int i = 0; i < theBuffers.Length; i++) { if (theBuffers[i] != null) { theBuffers[i].Stream.Dispose(); theBuffers[i] = null; } } theBuffers = null; if (oggStream != null) { oggStream.Close(); oggStream = null; } PcmStream.Dispose(); PcmStream = null; //We must loop this way, //since unlike the 32-bit implementation, //64-bit does not support native seek. if (PcmBytes == 0 && loop) { if (!stopNow) { continue; } else { break; } } else { //if we're not looping break; } //if we ran out of data but want to loop back } //outer loop to control //loop of file on 64-bit implementation //Finally, notify calling thread //that we're done playing. if (stopEvent != null) { stopEvent(); } } //method