public void Initialize(Stream stream, AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            InitializeReplayGainFilter(info, metadata, settings);

            _oggStream = new OggStream(settings.TryGetValue("SerialNumber", out int serialNumber)
                ? serialNumber
                : new Random().Next());

            // Default to a quality setting of 5
            if (settings.TryGetValue("BitRate", out int bitRate))
            {
                if (settings.TryGetValue("ForceCBR", out bool cbr) && cbr)
                {
                    _encoder = new VorbisEncoder(info.Channels, info.SampleRate,
                                                 bitRate * 1000, bitRate * 1000, bitRate * 1000);
                }
                else
                {
                    _encoder = new VorbisEncoder(info.Channels, info.SampleRate,
                                                 -1, bitRate * 1000, -1);
                }
            }
            else
            {
                _encoder = new VorbisEncoder(info.Channels, info.SampleRate,
                                             settings.TryGetValue("Quality", out int quality)
                        ? quality / 10f
                        : 0.5f);
            }

            // Generate the header
            using (var comment = new MetadataToVorbisCommentAdapter(metadata))
            {
                comment.HeaderOut(_encoder.DspState, out var first, out var second, out var third);
                _oggStream.PacketIn(first);
                _oggStream.PacketIn(second);
                _oggStream.PacketIn(third);
            }

            // Buffer the header in memory
            using (var tempStream = new MemoryStream())
            {
                _outputStream = tempStream;

                // ReSharper disable once PossibleNullReferenceException
                while (_oggStream.Flush(out var page))
                {
                    WritePage(page);
                }

                // Pre-allocate the whole stream (estimate worst case of 500kbps, plus the header)
                stream.SetLength(0xFA00 * (long)info.PlayLength.TotalSeconds + tempStream.Length);

                // Flush the headers to the output stream
                tempStream.WriteTo(stream);
            }

            _outputStream = stream;
        }
        void WriteFrames(int frames)
        {
            // ReSharper disable once PossibleNullReferenceException
            _encoder.Wrote(frames);

            while (_encoder.BlockOut())
            {
                _encoder.Analysis(IntPtr.Zero);
                _encoder.AddBlock();

                // ReSharper disable once PossibleNullReferenceException
                while (_encoder.FlushPacket(out var packet))
                {
                    // ReSharper disable once PossibleNullReferenceException
                    _oggStream.PacketIn(packet);

                    // ReSharper disable once PossibleNullReferenceException
                    while (_oggStream.PageOut(out var page))
                    {
                        WritePage(page);
                    }
                }
            }
        }