Example #1
0
        public void Initialize(Stream stream, AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            _stream = stream;

            InitializeReplayGainFilter(info, metadata, settings);

            // Call the external ID3 encoder, if available
            var metadataEncoderFactory =
                ExtensionProvider.GetFactories <IAudioMetadataEncoder>("Extension", FileExtension).FirstOrDefault();

            if (metadataEncoderFactory != null)
            {
                using (var export = metadataEncoderFactory.CreateExport())
                    using (var tempStream = new MemoryStream())
                    {
                        // Buffer the tag in memory
                        export.Value.WriteMetadata(tempStream, metadata, settings);

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

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

            _encoder = new(stream);
            _encoder.SetChannels(info.Channels);
            _encoder.SetSampleRate(info.SampleRate);
            if (info.FrameCount > 0)
            {
                _encoder.SetSampleCount((uint)info.FrameCount);
            }

            if (settings.TryGetValue("BitRate", out int bitRate))
            {
                // Use ABR, unless ForceCBR is set to true
                if (settings.TryGetValue("ForceCBR", out bool forceCbr) && forceCbr)
                {
                    _encoder.SetBitRate(bitRate);
                }
                else
                {
                    _encoder.SetVbrMeanBitRate(bitRate);
                    _encoder.SetVbrMode(VbrMode.Abr);
                }
            }
            else
            {
                // Use VBR quality 3 if nothing else is specified
                _encoder.SetVbrQuality(
                    settings.TryGetValue("VBRQuality", out int vbrQuality)
                        ? vbrQuality
                        : 3);
                _encoder.SetVbrMode(VbrMode.Mtrh);
            }

            _encoder.InitializeParameters();
        }
        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;
        }
Example #3
0
        public void Initialize(Stream stream, AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            _stream   = stream;
            _metadata = metadata;
            _settings = settings;

            InitializeReplayGainFilter(info, metadata, settings);

            var inputDescription = GetInputDescription(info);

            _audioFile = new(GetOutputDescription(inputDescription), AudioFileType.M4A, stream);
            _audioFile.SetProperty(ExtendedAudioFilePropertyId.ClientDataFormat, inputDescription);

            var converter = _audioFile.GetProperty <IntPtr>(ExtendedAudioFilePropertyId.AudioConverter);

            var logger = LoggerManager.LoggerFactory.CreateLogger <AacAudioEncoder>();

            // Enable high quality (defaults to medium, 0x40)
            SetConverterProperty(converter, AudioConverterPropertyId.CodecQuality, 0x60);

            if (settings.TryGetValue("BitRate", out int bitRate))
            {
                switch (bitRate)
                {
                case > 256 when info.Channels == 1:
                    logger.LogWarning("The maximum bitrate for 1-channel audio is 256 kbps.");
                    bitRate = 256;
                    break;

                case < 64 when info.Channels == 2:
                    logger.LogWarning("The minimum bitrate for 2-channel audio is 64 kbps.");
                    bitRate = 64;
                    break;
                }

                SetConverterProperty(converter, AudioConverterPropertyId.BitRate, bitRate * 1000);

                // Set the control mode (constrained is the default)
                var controlMode = BitrateControlMode.VariableConstrained;
                if (settings.TryGetValue("ControlMode", out string?controlModeValue))
                {
                    if (controlModeValue !.Equals("Average", StringComparison.OrdinalIgnoreCase))
                    {
                        controlMode = BitrateControlMode.LongTermAverage;
                    }
                    else if (controlModeValue.Equals("Constant", StringComparison.OrdinalIgnoreCase))
                    {
                        controlMode = BitrateControlMode.Constant;
                    }
                }
                SetConverterProperty(converter, AudioConverterPropertyId.BitRateControlMode, (uint)controlMode);
            }
Example #4
0
        public void Initialize(AudioInfo info, SettingDictionary settings, GroupToken groupToken)
        {
            _analyzer = new R128Analyzer((uint)info.Channels, (uint)info.SampleRate,
                                         settings.TryGetValue("PeakAnalysis", out string peakAnalysis) &&
                                         peakAnalysis.Equals("Interpolated", StringComparison.Ordinal));

            _groupState = (GroupState)groupToken.GetOrSetGroupState(new GroupState());
            // ReSharper disable once PossibleNullReferenceException
            _groupState.Handles.Enqueue(_analyzer.Handle);
        }
Example #5
0
        public void Initialize(AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            if (settings.TryGetValue("ApplyGain", out string applyGain))
            {
                _scale = applyGain.Equals("Track", StringComparison.OrdinalIgnoreCase)
                    ? CalculateScale(metadata.TrackGain, metadata.TrackPeak)
                    : CalculateScale(metadata.AlbumGain, metadata.AlbumPeak);
            }

            // Adjust the metadata so that it remains valid
            metadata.TrackPeak = CalculatePeak(metadata.TrackPeak, _scale);
            metadata.AlbumPeak = CalculatePeak(metadata.AlbumPeak, _scale);
            metadata.TrackGain = CalculateGain(metadata.TrackGain, _scale);
            metadata.AlbumGain = CalculateGain(metadata.AlbumGain, _scale);
        }
Example #6
0
        public void Initialize(Stream stream, AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            InitializeReplayGainFilter(info, metadata, settings);

            if (!settings.TryGetValue("SerialNumber", out int serialNumber))
#if NETSTANDARD2_0
            { using (var random = RandomNumberGenerator.Create())
              {
                  var buffer = new byte[sizeof(int)];
                  random.GetNonZeroBytes(buffer);
                  serialNumber = BitConverter.ToInt32(buffer, 0);
              } }
#else
            { serialNumber = RandomNumberGenerator.GetInt32(int.MaxValue); }
#endif

            _oggStream = new(serialNumber);

            // Default to a quality setting of 5
            if (settings.TryGetValue("BitRate", out int bitRate))
            {
                if (settings.TryGetValue("ForceCBR", out bool cbr) && cbr)
                {
                    _encoder = new(info.Channels, info.SampleRate, bitRate * 1000, bitRate * 1000, bitRate * 1000);
                }
                else
                {
                    _encoder = new(info.Channels, info.SampleRate, -1, bitRate * 1000, -1);
                }
            }
            else
            {
                _encoder = new(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;

                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;
        }
Example #7
0
        public void Initialize(Stream stream, AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            var gain = 0;

            if (settings.TryGetValue("ApplyGain", out string applyGain))
            {
                var scale = applyGain.Equals("Track", StringComparison.OrdinalIgnoreCase)
                    ? CalculateScale(metadata.TrackGain, metadata.TrackPeak)
                    : CalculateScale(metadata.AlbumGain, metadata.AlbumPeak);

                // Adjust the metadata so that it remains valid
                metadata.TrackGain = CalculateGain(metadata.TrackGain, scale);
                metadata.AlbumGain = CalculateGain(metadata.AlbumGain, scale);

                gain = (int)Math.Round(Math.Log10(scale) * 5120);
            }

            _comments = new MetadataToOpusCommentAdapter(metadata);
            _encoder  = new Encoder(stream, info.SampleRate, info.Channels, (int)info.PlayLength.TotalSeconds,
                                    _comments.Handle);

            if (info.BitsPerSample > 0)
            {
                _encoder.SetLsbDepth(Math.Min(Math.Max(info.BitsPerSample, 8), 24));
            }

            _encoder.SetHeaderGain(gain);

            if (!settings.TryGetValue("SerialNumber", out int serialNumber))
            {
                serialNumber = new Random().Next();
            }
            _encoder.SetSerialNumber(serialNumber);

            // Default to full VBR
            if (settings.TryGetValue("ControlMode", out string vbrMode))
            {
                switch (vbrMode)
                {
                case "Variable":
                    _encoder.SetVbrConstraint(false);
                    break;

                // 'Constrained' is the libopusenc default

                case "Constant":
                    _encoder.SetVbr(false);
                    break;
                }
            }
            else
            {
                _encoder.SetVbrConstraint(false);
            }

            if (settings.TryGetValue("BitRate", out int bitRate))
            {
                _encoder.SetBitRate(bitRate);
            }

            if (settings.TryGetValue("SignalType", out string signalType))
            {
                _encoder.SetSignal(signalType.Equals("Speech", StringComparison.OrdinalIgnoreCase)
                    ? SignalType.Speech
                    : SignalType.Music);
            }
            else
            {
                _encoder.SetSignal(SignalType.Music);
            }
        }
Example #8
0
        public void Initialize(Stream stream, AudioInfo info, AudioMetadata metadata, SettingDictionary settings)
        {
            _stream   = stream;
            _metadata = metadata;
            _settings = settings;

            InitializeReplayGainFilter(info, metadata, settings);

            var inputDescription = GetInputDescription(info);

            _audioFile = new ExtendedAudioFile(GetOutputDescription(inputDescription), AudioFileType.M4A, stream);
            _audioFile.SetProperty(ExtendedAudioFilePropertyId.ClientDataFormat, inputDescription);

            var converter = _audioFile.GetProperty <IntPtr>(ExtendedAudioFilePropertyId.AudioConverter);

            var logger = LoggerManager.LoggerFactory.CreateLogger <AacAudioEncoder>();

            // Enable high quality (defaults to medium, 0x40)
            SetConverterProperty(converter, AudioConverterPropertyId.CodecQuality, 0x60);

            if (settings.TryGetValue("BitRate", out int bitRate))
            {
                if (bitRate > 256 && info.Channels == 1)
                {
                    logger.LogWarning("The maximum bitrate for 1-channel audio is 256 kbps.");
                    bitRate = 256;
                }
                else if (bitRate < 64 && info.Channels == 2)
                {
                    logger.LogWarning("The minimum bitrate for 2-channel audio is 64 kbps.");
                    bitRate = 64;
                }

                SetConverterProperty(converter, AudioConverterPropertyId.BitRate, bitRate * 1000);

                // Set the control mode (constrained is the default)
                var controlMode = BitrateControlMode.VariableConstrained;
                if (settings.TryGetValue("ControlMode", out string controlModeValue))
                {
                    if (controlModeValue.Equals("Average", StringComparison.OrdinalIgnoreCase))
                    {
                        controlMode = BitrateControlMode.LongTermAverage;
                    }
                    else if (controlModeValue.Equals("Constant", StringComparison.OrdinalIgnoreCase))
                    {
                        controlMode = BitrateControlMode.Constant;
                    }
                }
                SetConverterProperty(converter, AudioConverterPropertyId.BitRateControlMode, (uint)controlMode);
            }
            else
            {
                // Enable a true variable bitrate
                SetConverterProperty(converter, AudioConverterPropertyId.BitRateControlMode,
                                     (uint)BitrateControlMode.Variable);

                // Use a default VBR quality index of 9
                SetConverterProperty(converter, AudioConverterPropertyId.VbrQuality,
                                     settings.TryGetValue("VBRQuality", out int quality)
                        ? _vbrQualities[quality]
                        : _vbrQualities[9]);
            }

            // Setting the ConverterConfig property to null resynchronizes the converter settings
            _audioFile.SetProperty(ExtendedAudioFilePropertyId.ConverterConfig, IntPtr.Zero);
        }