/// <summary> /// The create audio. /// </summary> /// <param name="job"> /// The job. /// </param> /// <returns> /// The <see cref="Audio"/>. /// </returns> private static Audio CreateAudio(EncodeTask job) { Audio audio = new Audio(); List <uint> copyMaskList = new List <uint>(); if (job.AllowedPassthruOptions.AudioAllowAACPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_AAC_PASS); } if (job.AllowedPassthruOptions.AudioAllowAC3Pass) { copyMaskList.Add(NativeConstants.HB_ACODEC_AC3_PASS); } if (job.AllowedPassthruOptions.AudioAllowDTSHDPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_DCA_HD_PASS); } if (job.AllowedPassthruOptions.AudioAllowDTSPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_DCA_PASS); } if (job.AllowedPassthruOptions.AudioAllowEAC3Pass) { copyMaskList.Add(NativeConstants.HB_ACODEC_EAC3_PASS); } if (job.AllowedPassthruOptions.AudioAllowFlacPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_FLAC_PASS); } if (job.AllowedPassthruOptions.AudioAllowMP3Pass) { copyMaskList.Add(NativeConstants.HB_ACODEC_MP3_PASS); } if (job.AllowedPassthruOptions.AudioAllowTrueHDPass) { copyMaskList.Add(NativeConstants.HB_ACODEC_TRUEHD_PASS); } audio.CopyMask = copyMaskList.ToArray(); HBAudioEncoder audioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(job.AllowedPassthruOptions.AudioEncoderFallback)); audio.FallbackEncoder = audioEncoder.Id; audio.AudioList = new List <HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack>(); foreach (AudioTrack item in job.AudioTracks) { HBAudioEncoder encoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(item.Encoder)); Validate.NotNull(encoder, "Unrecognized audio encoder:" + item.Encoder); HBMixdown mixdown = HandBrakeEncoderHelpers.GetMixdown(item.MixDown); HBRate sampleRate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(s => s.Name == item.SampleRate.ToString(CultureInfo.InvariantCulture)); HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack audioTrack = new HandBrake.ApplicationServices.Interop.Json.Encode.AudioTrack { Track = (item.Track.HasValue ? item.Track.Value : 0) - 1, DRC = item.DRC, Encoder = encoder.Id, Gain = item.Gain, Mixdown = mixdown != null ? mixdown.Id : -1, NormalizeMixLevel = false, Samplerate = sampleRate != null ? sampleRate.Rate : 0, Name = item.TrackName, }; if (!item.IsPassthru) { if (item.EncoderRateType == AudioEncoderRateType.Quality) { audioTrack.Quality = item.Quality; } if (item.EncoderRateType == AudioEncoderRateType.Bitrate) { audioTrack.Bitrate = item.Bitrate; } } audio.AudioList.Add(audioTrack); } return(audio); }
/// <summary> /// The get default quality. /// </summary> /// <param name="encoder"> /// The encoder. /// </param> /// <returns> /// The <see cref="double"/>. /// </returns> public static double GetDefaultQuality(HBAudioEncoder encoder) { return(HBFunctions.hb_audio_quality_get_default((uint)encoder.Id)); }
/// <summary> /// The get default audio compression. /// </summary> /// <param name="encoder"> /// The encoder. /// </param> /// <returns> /// The <see cref="double"/>. /// </returns> public static double GetDefaultAudioCompression(HBAudioEncoder encoder) { return(HBFunctions.hb_audio_compression_get_default((uint)encoder.Id)); }
/// <summary> /// Determines if the given encoder is compatible with the given track. /// </summary> /// <param name="codecId"> /// The codec Id. /// </param> /// <param name="encoder"> /// The encoder to examine. /// </param> /// <returns> /// True if the given encoder is compatible with the given audio track. /// </returns> /// <remarks> /// Only works with passthrough encoders. /// </remarks> public static bool AudioEncoderIsCompatible(int codecId, HBAudioEncoder encoder) { return((codecId & encoder.Id) > 0); }
public AudioOutputPreview GetAudioPreview(AudioTrack inputTrack, AudioEncodingViewModel audioVM) { HBAudioEncoder encoder = audioVM.HBAudioEncoder; var outputPreviewTrack = new AudioOutputPreview { Name = inputTrack.NoTrackDisplay, Encoder = encoder.DisplayName }; if (encoder.IsPassthrough) { // For passthrough encodes, we need to make sure the input track is of the right type if (!Encoders.AudioEncoderIsCompatible(inputTrack, encoder) && encoder.ShortName != "copy") { return(null); } HBContainer container = Encoders.GetContainer(this.Profile.ContainerName); if (encoder.ShortName == "copy" && (inputTrack.Codec == AudioCodec.Dts || inputTrack.Codec == AudioCodec.DtsHD) && container.DefaultExtension == "mp4") { this.PassthroughWarningText = EncodingRes.DtsMp4Warning; this.PassthroughWarningVisible = true; return(outputPreviewTrack); } } // Find out what the real mixdown, sample rate and bitrate will be. HBMixdown mixdown; int sampleRate, bitrate; if (encoder.ShortName == "copy") { if (Encoders.AudioEncoderIsCompatible(inputTrack, encoder)) { return(outputPreviewTrack); } if (this.Profile.AudioEncoderFallback == null) { encoder = Encoders.AudioEncoders.First(a => !a.IsPassthrough); } else { encoder = Encoders.GetAudioEncoder(this.Profile.AudioEncoderFallback); } mixdown = Encoders.GetDefaultMixdown(encoder, inputTrack.ChannelLayout); sampleRate = 0; bitrate = 0; outputPreviewTrack.Encoder = encoder.DisplayName; } else { mixdown = audioVM.SelectedMixdown.Mixdown; sampleRate = audioVM.SampleRate; bitrate = audioVM.SelectedBitrate.Bitrate; } HBMixdown previewMixdown; previewMixdown = Encoders.SanitizeMixdown(mixdown, encoder, inputTrack.ChannelLayout); int previewSampleRate = sampleRate; if (previewSampleRate == 0) { previewSampleRate = inputTrack.SampleRate; } int previewBitrate = bitrate; if (previewBitrate == 0) { previewBitrate = Encoders.GetDefaultBitrate(encoder, previewSampleRate, previewMixdown); } else { previewBitrate = Encoders.SanitizeAudioBitrate(previewBitrate, encoder, previewSampleRate, previewMixdown); } outputPreviewTrack.Mixdown = previewMixdown.DisplayName; outputPreviewTrack.SampleRate = DisplayConversions.DisplaySampleRate(previewSampleRate); if (audioVM.EncodeRateType == AudioEncodeRateType.Bitrate) { if (previewBitrate >= 0) { outputPreviewTrack.Quality = previewBitrate + " kbps"; } else { outputPreviewTrack.Quality = string.Empty; } } else { outputPreviewTrack.Quality = "CQ " + audioVM.AudioQuality; } var modifiers = new List <string>(); if (audioVM.Gain != 0) { modifiers.Add(string.Format("{0}{1} dB", audioVM.Gain > 0 ? "+" : string.Empty, audioVM.Gain)); } if (audioVM.Drc != 0) { modifiers.Add("DRC " + audioVM.Drc.ToString()); } outputPreviewTrack.Modifiers = string.Join(", ", modifiers); return(outputPreviewTrack); }
/// <summary> /// Gets the default mixdown for the given audio encoder and channel layout. /// </summary> /// <param name="encoder">The output codec to be used.</param> /// <param name="layout">The input channel layout.</param> /// <returns>The default mixdown for the given codec and channel layout.</returns> public static HBMixdown GetDefaultMixdown(HBAudioEncoder encoder, ulong layout) { int defaultMixdown = HBFunctions.hb_get_default_mixdown((uint)encoder.Id, layout); return(Mixdowns.Single(m => m.Id == defaultMixdown)); }
/// <summary> /// Gets the default audio bitrate for the given parameters. /// </summary> /// <param name="encoder">The encoder to use.</param> /// <param name="sampleRate">The sample rate to use.</param> /// <param name="mixdown">The mixdown to use.</param> /// <returns>The default bitrate for these parameters.</returns> public static int GetDefaultBitrate(HBAudioEncoder encoder, int sampleRate, HBMixdown mixdown) { return(HBFunctions.hb_get_default_audio_bitrate((uint)encoder.Id, sampleRate, mixdown.Id)); }
/// <summary> /// Determines if DRC can be applied to the given track with the given encoder. /// </summary> /// <param name="track">The track to apply DRC to.</param> /// <param name="encoder">The encoder to use for DRC.</param> /// <returns>True if DRC can be applied to the track with the given encoder.</returns> public static bool CanApplyDrc(AudioTrack track, HBAudioEncoder encoder) { return(HBFunctions.hb_audio_can_apply_drc(track.CodecId, track.CodecParam, encoder.Id) > 0); }
/// <summary> /// The create audio. /// </summary> /// <param name="job"> /// The job. /// </param> /// <returns> /// The <see cref="Audio"/>. /// </returns> private static Audio CreateAudio(EncodeTask job) { Audio audio = new Audio(); List <string> copyMaskList = new List <string>(); if (job.AllowedPassthruOptions.AudioAllowAACPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.AacPassthru)); } if (job.AllowedPassthruOptions.AudioAllowAC3Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.Ac3Passthrough)); } if (job.AllowedPassthruOptions.AudioAllowDTSHDPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.DtsHDPassthrough)); } if (job.AllowedPassthruOptions.AudioAllowDTSPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.DtsPassthrough)); } if (job.AllowedPassthruOptions.AudioAllowEAC3Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.EAc3Passthrough)); } if (job.AllowedPassthruOptions.AudioAllowFlacPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.FlacPassthru)); } if (job.AllowedPassthruOptions.AudioAllowMP3Pass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.Mp3Passthru)); } if (job.AllowedPassthruOptions.AudioAllowTrueHDPass) { copyMaskList.Add(EnumHelper <AudioEncoder> .GetShortName(AudioEncoder.TrueHDPassthrough)); } audio.CopyMask = copyMaskList.ToArray(); HBAudioEncoder audioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(job.AllowedPassthruOptions.AudioEncoderFallback)); audio.FallbackEncoder = audioEncoder.ShortName; audio.AudioList = new List <HandBrake.Interop.Interop.Json.Encode.AudioTrack>(); foreach (AudioTrack item in job.AudioTracks) { HBAudioEncoder encoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(item.Encoder)); Validate.NotNull(encoder, "Unrecognized audio encoder:" + item.Encoder); if (item.IsPassthru && (item.ScannedTrack.Codec & encoder.Id) == 0) { // We have an unsupported passthru. Rather than let libhb drop the track, switch it to the fallback. encoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(job.AllowedPassthruOptions.AudioEncoderFallback)); } HBMixdown mixdown = HandBrakeEncoderHelpers.GetMixdown(item.MixDown); HBRate sampleRate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(s => s.Name == item.SampleRate.ToString(CultureInfo.InvariantCulture)); HandBrake.Interop.Interop.Json.Encode.AudioTrack audioTrack = new HandBrake.Interop.Interop.Json.Encode.AudioTrack { Track = (item.Track.HasValue ? item.Track.Value : 0) - 1, DRC = item.DRC, Encoder = encoder.ShortName, Gain = item.Gain, Mixdown = mixdown != null ? mixdown.Id : -1, NormalizeMixLevel = false, Samplerate = sampleRate != null ? sampleRate.Rate : 0, Name = !string.IsNullOrEmpty(item.TrackName) ? item.TrackName : null, }; if (!item.IsPassthru) { if (item.EncoderRateType == AudioEncoderRateType.Quality) { audioTrack.Quality = item.Quality; } if (item.EncoderRateType == AudioEncoderRateType.Bitrate) { audioTrack.Bitrate = item.Bitrate; } } audio.AudioList.Add(audioTrack); } return(audio); }
public AudioEncodingViewModel(AudioEncoding audioEncoding, SourceTitle selectedTitle, List <int> chosenAudioTracks, AudioPanelViewModel audioPanelVM) { this.initializing = true; this.audioPanelVM = audioPanelVM; this.targetStreams = new ObservableCollection <TargetStreamViewModel>(); this.targetStreamIndex = audioEncoding.InputNumber; this.SetChosenTracks(chosenAudioTracks, selectedTitle); this.audioEncoders = new List <AudioEncoderViewModel>(); this.mixdownChoices = new List <MixdownViewModel>(); this.RefreshEncoderChoices(); this.presetChangeSubscription = this.presetsService.WhenAnyValue(x => x.SelectedPreset.Preset.EncodingProfile) .Subscribe(profile => { this.containerSubscription?.Dispose(); this.containerSubscription = profile.WhenAnyValue(x => x.ContainerName) .Skip(1) .Subscribe(_ => { this.RefreshEncoderChoices(isContainerChange: true); }); this.audioPanelVM.SuppressProfileEdits = true; this.RefreshEncoderChoices(); this.audioPanelVM.SuppressProfileEdits = false; }); HBAudioEncoder hbAudioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(audioEncoding.Encoder); if (hbAudioEncoder.IsPassthrough) { this.selectedAudioEncoder = this.audioEncoders[0]; this.selectedPassthrough = audioEncoding.Encoder; } else { this.selectedAudioEncoder = this.audioEncoders.Skip(1).FirstOrDefault(e => e.Encoder.ShortName == audioEncoding.Encoder); this.selectedPassthrough = "copy"; } if (this.selectedAudioEncoder == null) { this.selectedAudioEncoder = this.audioEncoders[1]; } this.RefreshMixdownChoices(); this.RefreshBitrateChoices(); this.RefreshSampleRateChoices(); this.SelectMixdown(HandBrakeEncoderHelpers.GetMixdown(audioEncoding.Mixdown)); this.sampleRate = audioEncoding.SampleRateRaw; if (!this.HBAudioEncoder.SupportsQuality) { this.encodeRateType = AudioEncodeRateType.Bitrate; } else { this.encodeRateType = audioEncoding.EncodeRateType; } this.audioQuality = audioEncoding.Quality; if (audioEncoding.Compression >= 0) { this.audioCompression = audioEncoding.Compression; } else { this.audioCompression = this.HBAudioEncoder.DefaultCompression; } this.selectedBitrate = this.BitrateChoices.SingleOrDefault(b => b.Bitrate == audioEncoding.Bitrate); if (this.selectedBitrate == null) { this.selectedBitrate = this.BitrateChoices.First(); } this.gain = audioEncoding.Gain; this.drc = audioEncoding.Drc; this.passthroughIfPossible = audioEncoding.PassthroughIfPossible; this.name = audioEncoding.Name; // EncoderSettingsVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, x => x.SelectedPassthrough, (audioEncoder, passthrough) => { if (audioEncoder == null) { return(false); } if (passthrough == null) { return(false); } return(!GetHBAudioEncoder(audioEncoder, passthrough).IsPassthrough); }).ToProperty(this, x => x.EncoderSettingsVisible, out this.encoderSettingsVisible); // AudioCompressionVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { return(!audioEncoder.IsPassthrough && audioEncoder.Encoder.SupportsCompression); }).ToProperty(this, x => x.AudioCompressionVisible, out this.audioCompressionVisible); // PassthroughIfPossibleVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(false); } if (HandBrakeEncoderHelpers.AudioEncoders.Any(e => e.Id == (NativeConstants.HB_ACODEC_PASS_FLAG | audioEncoder.Encoder.Id))) { return(true); } return(audioEncoder.Encoder.ShortName.ToLowerInvariant().Contains("aac") || audioEncoder.Encoder.ShortName.ToLowerInvariant().Contains("mp3")); }).ToProperty(this, x => x.PassthroughIfPossibleVisible, out this.passthroughIfPossibleVisible); // BitrateVisible this.WhenAnyValue( x => x.SelectedAudioEncoder, x => x.EncoderSettingsVisible, x => x.SelectedMixdown, x => x.EncodeRateType, (audioEncoder, encoderSettingsVisible, mixdown, encodeRateType) => { if (audioEncoder.IsPassthrough) { return(false); } if (encoderSettingsVisible && mixdown != null && encodeRateType == AudioEncodeRateType.Bitrate) { // We only need to find out if the bitrate limits exist, so pass in some normal values for sample rate and mixdown. BitrateLimits bitrateLimits = HandBrakeEncoderHelpers.GetBitrateLimits(audioEncoder.Encoder, 48000, HandBrakeEncoderHelpers.GetMixdown("dpl2")); return(bitrateLimits.High > 0); } return(false); }).ToProperty(this, x => x.BitrateVisible, out this.bitrateVisible); // BitrateLabelVisible this.WhenAnyValue(x => x.BitrateVisible, x => x.SelectedAudioEncoder, (bitrateVisible, audioEncoder) => { return(!audioEncoder.IsPassthrough && bitrateVisible && !audioEncoder.Encoder.SupportsQuality); }).ToProperty(this, x => x.BitrateLabelVisible, out this.bitrateLabelVisible); // AudioQualityVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, x => x.EncodeRateType, (audioEncoder, encodeRateType) => { return(!audioEncoder.IsPassthrough && audioEncoder.Encoder.SupportsQuality && encodeRateType == AudioEncodeRateType.Quality); }).ToProperty(this, x => x.AudioQualityVisible, out this.audioQualityVisible); // AudioQualityRadioVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { return(!audioEncoder.IsPassthrough && audioEncoder.Encoder.SupportsQuality); }).ToProperty(this, x => x.AudioQualityRadioVisible, out this.audioQualityRadioVisible); // AudioQualityMinimum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.QualityLimits.Low, RangeRoundDigits)); }).ToProperty(this, x => x.AudioQualityMinimum, out this.audioQualityMinimum); // AudioQualityMaximum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.QualityLimits.High, RangeRoundDigits)); }).ToProperty(this, x => x.AudioQualityMaximum, out this.audioQualityMaximum); // AudioQualityGranularity this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.QualityLimits.Granularity, RangeRoundDigits)); }).ToProperty(this, x => x.AudioQualityGranularity, out this.audioQualityGranularity); // AudioQualityToolTip this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(string.Empty); } string directionSentence; if (audioEncoder.Encoder.QualityLimits.Ascending) { directionSentence = EncodingRes.AscendingQualityToolTip; } else { directionSentence = EncodingRes.DescendingQualityToolTip; } return(string.Format( EncodingRes.AudioQualityToolTip, directionSentence, audioEncoder.Encoder.QualityLimits.Low, audioEncoder.Encoder.QualityLimits.High)); }).ToProperty(this, x => x.AudioQualityToolTip, out this.audioQualityToolTip); // AudioCompressionMinimum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.CompressionLimits.Low, RangeRoundDigits)); }).ToProperty(this, x => x.AudioCompressionMinimum, out this.audioCompressionMinimum); // AudioCompressionMaximum this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.CompressionLimits.High, RangeRoundDigits)); }).ToProperty(this, x => x.AudioCompressionMaximum, out this.audioCompressionMaximum); // AudioCompressionGranularity this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(0); } return(Math.Round(audioEncoder.Encoder.CompressionLimits.Granularity, RangeRoundDigits)); }).ToProperty(this, x => x.AudioCompressionGranularity, out this.audioCompressionGranularity); // AudioCompressionToolTip this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { if (audioEncoder.IsPassthrough) { return(string.Empty); } string directionSentence; if (audioEncoder.Encoder.QualityLimits.Ascending) { directionSentence = EncodingRes.AscendingCompressionToolTip; } else { directionSentence = EncodingRes.DescendingCompressionToolTip; } return(string.Format( EncodingRes.AudioCompressionToolTip, directionSentence, audioEncoder.Encoder.CompressionLimits.Low, audioEncoder.Encoder.CompressionLimits.High)); }).ToProperty(this, x => x.AudioCompressionToolTip, out this.audioCompressionToolTip); // PassthroughChoicesVisible this.WhenAnyValue(x => x.SelectedAudioEncoder, audioEncoder => { return(audioEncoder.IsPassthrough); }).ToProperty(this, x => x.PassthroughChoicesVisible, out this.passthroughChoicesVisible); this.selectedTitleSubscription = this.main.WhenAnyValue(x => x.SelectedTitle) .Skip(1) .Subscribe(_ => { this.RefreshFromNewInput(); }); this.audioTrackChangedSubscription = this.main.AudioTracks.Connect().WhenAnyPropertyChanged().Subscribe(_ => { this.RefreshFromNewInput(); }); Config.Observables.ShowAudioTrackNameField.ToProperty(this, x => x.NameVisible, out this.nameVisible); this.initializing = false; }
public AudioOutputPreview GetAudioPreview(SourceAudioTrack inputTrack, AudioEncodingViewModel audioVM) { HBAudioEncoder encoder = audioVM.HBAudioEncoder; var outputPreviewTrack = new AudioOutputPreview { Name = inputTrack.Description, Encoder = encoder.DisplayName }; if (encoder.IsPassthrough) { // For passthrough encodes, we need to make sure the input track is of the right type if (!HandBrakeEncoderHelpers.AudioEncoderIsCompatible(inputTrack.Codec, encoder) && encoder.ShortName != "copy") { return(null); } } if (encoder.ShortName == "copy") { if (this.CopyMaskChoices.Any( choice => { if (!choice.Enabled) { return(false); } return((HandBrakeEncoderHelpers.GetAudioEncoder("copy:" + choice.Codec).Id & inputTrack.Codec) > 0); })) { return(outputPreviewTrack); } if (this.Profile.AudioEncoderFallback == null) { encoder = HandBrakeEncoderHelpers.AudioEncoders.First(a => !a.IsPassthrough); } else { encoder = HandBrakeEncoderHelpers.GetAudioEncoder(this.Profile.AudioEncoderFallback); } // Get the default output values for the input track and encoder var defaultSettings = AudioUtilities.GetDefaultSettings(inputTrack, encoder); // Apply the output values to the preview object UpdateAudioPreviewTrack(outputPreviewTrack, defaultSettings); } else { HBMixdown previewMixdown; previewMixdown = HandBrakeEncoderHelpers.SanitizeMixdown(audioVM.SelectedMixdown.Mixdown, encoder, (ulong)inputTrack.ChannelLayout); int previewSampleRate = audioVM.SampleRate; if (previewSampleRate == 0) { previewSampleRate = inputTrack.SampleRate; } // Collect the output values in the AudioTrack object var outputTrack = new OutputAudioTrackInfo { Encoder = encoder, Mixdown = previewMixdown, SampleRate = HandBrakeEncoderHelpers.SanitizeSampleRate(encoder, previewSampleRate), EncodeRateType = audioVM.EncodeRateType }; if (audioVM.EncodeRateType == AudioEncodeRateType.Bitrate) { int previewBitrate = audioVM.SelectedBitrate.Bitrate; if (previewBitrate == 0) { previewBitrate = HandBrakeEncoderHelpers.GetDefaultBitrate(encoder, previewSampleRate, previewMixdown); } else { previewBitrate = HandBrakeEncoderHelpers.SanitizeAudioBitrate(previewBitrate, encoder, previewSampleRate, previewMixdown); } outputTrack.Bitrate = previewBitrate; } else { outputTrack.Quality = audioVM.AudioQuality; } outputTrack.Gain = audioVM.Gain; outputTrack.Drc = audioVM.Drc; // Apply the output values to the preview object UpdateAudioPreviewTrack(outputPreviewTrack, outputTrack); } return(outputPreviewTrack); }
/// <summary> /// Initializes a new instance of the <see cref="AudioTrack"/> class. /// Create a track from a behaviour track. /// </summary> /// <param name="track"> /// The Behavior track /// </param> /// <param name="sourceTrack"> /// The source track we are dealing with. /// </param> /// <param name="fallback"> /// An encoder to fall back to. /// </param> public AudioTrack(AudioBehaviourTrack track, Audio sourceTrack, AllowedPassthru fallback, OutputFormat container) { AudioEncoder chosenEncoder = track.Encoder; HBAudioEncoder encoderInfo = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(track.Encoder)); if (track.IsPassthru && (sourceTrack.Codec & encoderInfo.Id) == 0) { chosenEncoder = fallback.AudioEncoderFallback; } if (track.IsPassthru && chosenEncoder == AudioEncoder.Passthrough) { HBAudioEncoder fallbackEncoderInfo = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(fallback.AudioEncoderFallback)); if (fallbackEncoderInfo != null) { int format = HandBrakeEncoderHelpers.GetContainer(EnumHelper <OutputFormat> .GetShortName(container)).Id; int copyMask = checked ((int)HandBrakeEncoderHelpers.BuildCopyMask( fallback.AudioAllowMP3Pass, fallback.AudioAllowAACPass, fallback.AudioAllowAC3Pass, fallback.AudioAllowDTSPass, fallback.AudioAllowDTSHDPass, fallback.AudioAllowEAC3Pass, fallback.AudioAllowFlacPass, fallback.AudioAllowTrueHDPass)); HBAudioEncoder autoPassthruEncoderOption = HandBrakeEncoderHelpers.GetAutoPassthruEncoder(sourceTrack.Codec, copyMask, fallbackEncoderInfo.Id, format); AudioEncoder autoPassthru = EnumHelper <AudioEncoder> .GetValue(autoPassthruEncoderOption.ShortName); chosenEncoder = autoPassthru; } } encoderInfo = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper <AudioEncoder> .GetShortName(chosenEncoder)); this.scannedTrack = sourceTrack; this.drc = track.DRC; this.encoder = chosenEncoder; this.gain = track.Gain; this.mixDown = track.MixDown != null ? track.MixDown.ShortName : "dpl2"; // If the mixdown isn't supported, downgrade it. if (track.IsPassthru && track.MixDown != null && encoderInfo != null && !HandBrakeEncoderHelpers.MixdownIsSupported(track.MixDown, encoderInfo, sourceTrack.ChannelLayout)) { HBMixdown changedMixdown = HandBrakeEncoderHelpers.GetDefaultMixdown(encoderInfo, (ulong)sourceTrack.ChannelLayout); if (changedMixdown != null) { this.mixDown = changedMixdown.ShortName; } } this.sampleRate = track.SampleRate; this.encoderRateType = track.EncoderRateType; this.quality = track.Quality; this.bitrate = track.Bitrate; if (!string.IsNullOrEmpty(this.scannedTrack?.Name)) { this.TrackName = this.scannedTrack.Name; } this.SetupLimits(); }
/// <summary> /// Determines if DRC can be applied to the given track with the given encoder. /// </summary> /// <param name="trackNumber"> /// The track Number. /// </param> /// <param name="encoder"> /// The encoder to use for DRC. /// </param> /// <param name="title"> /// The title. /// </param> /// <returns> /// True if DRC can be applied to the track with the given encoder. /// </returns> public static bool CanApplyDrc(IntPtr handle, int trackNumber, HBAudioEncoder encoder, int title) { return(hbFunctions.hb_audio_can_apply_drc2(handle, title, trackNumber, encoder.Id) > 0); }
public static OutputAudioTrackInfo GetDefaultSettings(SourceAudioTrack source, HBAudioEncoder encoder) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (encoder == null) { throw new ArgumentNullException(nameof(encoder)); } var result = new OutputAudioTrackInfo { Encoder = encoder, Drc = 0, Gain = 0, SampleRate = HandBrakeEncoderHelpers.SanitizeSampleRate(encoder, source.SampleRate) }; if (encoder.SupportsCompression) { result.CompressionLevel = HandBrakeEncoderHelpers.GetDefaultAudioCompression(encoder); } HBMixdown mixdown = HandBrakeEncoderHelpers.GetDefaultMixdown(encoder, (ulong)source.ChannelLayout); result.Mixdown = mixdown; // For some reason HB does not honor Quality when falling back to an encoder during auto-passthrough. // For now we do bitrate only. //if (encoder.SupportsQuality) //{ // result.EncodeRateType = AudioEncodeRateType.Quality; // result.Quality = HandBrakeEncoderHelpers.GetDefaultQuality(encoder); //} //else //{ result.EncodeRateType = AudioEncodeRateType.Bitrate; result.Bitrate = HandBrakeEncoderHelpers.GetDefaultBitrate(encoder, result.SampleRate, mixdown); //} return(result); }
/// <summary> /// Determines if the given encoder is compatible with the given track. /// </summary> /// <param name="track">The audio track to examine.</param> /// <param name="encoder">The encoder to examine.</param> /// <returns>True if the given encoder is comatible with the given audio track.</returns> /// <remarks>Only works with passthrough encoders.</remarks> public static bool AudioEncoderIsCompatible(AudioTrack track, HBAudioEncoder encoder) { return((track.CodecId & encoder.Id) > 0); }
public AudioEncodingViewModel(AudioEncoding audioEncoding, Title selectedTitle, List <int> chosenAudioTracks, string containerName, AudioPanelViewModel audioPanelVM) { this.initializing = true; this.audioPanelVM = audioPanelVM; this.targetStreams = new ObservableCollection <TargetStreamViewModel>(); this.targetStreamIndex = audioEncoding.InputNumber; this.SetChosenTracks(chosenAudioTracks, selectedTitle); this.audioEncoders = new List <AudioEncoderViewModel>(); this.mixdownChoices = new List <MixdownViewModel>(); this.containerName = containerName; this.RefreshEncoderChoices(); HBAudioEncoder hbAudioEncoder = Encoders.GetAudioEncoder(audioEncoding.Encoder); if (hbAudioEncoder.IsPassthrough) { this.selectedAudioEncoder = this.audioEncoders[0]; this.selectedPassthrough = audioEncoding.Encoder; } else { this.selectedAudioEncoder = this.audioEncoders.Skip(1).FirstOrDefault(e => e.Encoder.ShortName == audioEncoding.Encoder); this.selectedPassthrough = "copy"; } if (this.selectedAudioEncoder == null) { this.selectedAudioEncoder = this.audioEncoders[1]; } this.RefreshMixdownChoices(); this.RefreshBitrateChoices(); this.RefreshSampleRateChoices(); this.SelectMixdown(Encoders.GetMixdown(audioEncoding.Mixdown)); this.sampleRate = audioEncoding.SampleRateRaw; if (!this.HBAudioEncoder.SupportsQuality) { this.encodeRateType = AudioEncodeRateType.Bitrate; } else { this.encodeRateType = audioEncoding.EncodeRateType; } this.audioQuality = audioEncoding.Quality; if (audioEncoding.Compression >= 0) { this.audioCompression = audioEncoding.Compression; } else { this.audioCompression = this.HBAudioEncoder.DefaultCompression; } this.selectedBitrate = this.BitrateChoices.SingleOrDefault(b => b.Bitrate == audioEncoding.Bitrate); if (this.selectedBitrate == null) { this.selectedBitrate = this.BitrateChoices.First(); } this.gain = audioEncoding.Gain; this.drc = audioEncoding.Drc; this.passthroughIfPossible = audioEncoding.PassthroughIfPossible; this.name = audioEncoding.Name; Messenger.Default.Register <SelectedTitleChangedMessage>( this, message => { this.RefreshMixdownChoices(); this.RefreshBitrateChoices(); this.RefreshDrc(); }); Messenger.Default.Register <AudioInputChangedMessage>( this, message => { this.RefreshMixdownChoices(); this.RefreshBitrateChoices(); this.RefreshDrc(); }); Messenger.Default.Register <OptionsChangedMessage>( this, message => { this.RaisePropertyChanged(() => this.NameVisible); }); Messenger.Default.Register <ContainerChangedMessage>( this, message => { this.containerName = message.ContainerName; this.RefreshEncoderChoices(); }); this.initializing = false; }
/// <summary> /// Sanitizes a mixdown given the output codec and input channel layout. /// </summary> /// <param name="mixdown">The desired mixdown.</param> /// <param name="encoder">The output encoder to be used.</param> /// <param name="layout">The input channel layout.</param> /// <returns>A sanitized mixdown value.</returns> public static HBMixdown SanitizeMixdown(HBMixdown mixdown, HBAudioEncoder encoder, ulong layout) { int sanitizedMixdown = HBFunctions.hb_get_best_mixdown((uint)encoder.Id, layout, mixdown.Id); return(Mixdowns.Single(m => m.Id == sanitizedMixdown)); }
/// <summary> /// Determines if a mixdown is available for a given track and encoder. /// </summary> /// <param name="mixdown"> /// The mixdown to evaluate. /// </param> /// <param name="encoder"> /// The encoder to evaluate. /// </param> /// <param name="channelLayout">channel layout of the source track</param> /// <returns>True if available.</returns> public static bool MixdownIsSupported(HBMixdown mixdown, HBAudioEncoder encoder, long channelLayout) { return(HBFunctions.hb_mixdown_is_supported(mixdown.Id, (uint)encoder.Id, (uint)channelLayout) > 0); }
/// <summary> /// Sanitizes an audio bitrate given the output codec, sample rate and mixdown. /// </summary> /// <param name="audioBitrate">The desired audio bitrate.</param> /// <param name="encoder">The output encoder to be used.</param> /// <param name="sampleRate">The output sample rate to be used.</param> /// <param name="mixdown">The mixdown to be used.</param> /// <returns>A sanitized audio bitrate.</returns> public static int SanitizeAudioBitrate(int audioBitrate, HBAudioEncoder encoder, int sampleRate, HBMixdown mixdown) { return(HBFunctions.hb_get_best_audio_bitrate((uint)encoder.Id, audioBitrate, sampleRate, mixdown.Id)); }
/// <summary> /// Determines if DRC can be applied to the given track with the given encoder. /// </summary> /// <param name="trackNumber"> /// The track Number. /// </param> /// <param name="encoder"> /// The encoder to use for DRC. /// </param> /// <param name="title"> /// The title. /// </param> /// <returns> /// True if DRC can be applied to the track with the given encoder. /// </returns> public static bool CanApplyDrc(int trackNumber, HBAudioEncoder encoder, int title) { return(HBFunctions.hb_audio_can_apply_drc2(HandBrakeInstanceManager.LastScanHandle, title, trackNumber, encoder.Id) > 0); }
/// <summary> /// Determines if DRC can be applied to the given track with the given encoder. /// </summary> /// <param name="trackNumber">The track Number.</param> /// <param name="encoder">The encoder to use for DRC.</param> /// <param name="title">The title.</param> /// <returns>True if DRC can be applied to the track with the given encoder.</returns> public bool CanApplyDrc(int trackNumber, HBAudioEncoder encoder, int title) { return(HBFunctions.hb_audio_can_apply_drc2(this.hbHandle, title, trackNumber, encoder.Id) > 0); }
/// <summary> /// Sanitizes the given sample rate for the given encoder. /// </summary> /// <param name="encoder">The encoder.</param> /// <param name="sampleRate">The sample rate to sanitize.</param> /// <returns>The sanitized sample rate.</returns> public static int SanitizeSampleRate(HBAudioEncoder encoder, int sampleRate) { return(HBFunctions.hb_audio_samplerate_find_closest(sampleRate, (uint)encoder.Id)); }
/// <summary> /// Determines if the given encoder supports the given mixdown. /// </summary> /// <param name="mixdown"> /// The mixdown to evaluate. /// </param> /// <param name="encoder"> /// The encoder to evaluate. /// </param> /// <returns> /// True if the encoder supports the mixdown. /// </returns> public static bool MixdownHasCodecSupport(HBMixdown mixdown, HBAudioEncoder encoder) { return(HBFunctions.hb_mixdown_has_codec_support(mixdown.Id, (uint)encoder.Id) > 0); }
public AudioOutputPreview GetAudioPreview(SourceAudioTrack inputTrack, AudioEncodingViewModel audioVM) { HBAudioEncoder encoder = audioVM.HBAudioEncoder; var outputPreviewTrack = new AudioOutputPreview { Name = inputTrack.Description, Encoder = encoder.DisplayName }; if (encoder.IsPassthrough) { // For passthrough encodes, we need to make sure the input track is of the right type if (!HandBrakeEncoderHelpers.AudioEncoderIsCompatible(inputTrack.Codec, encoder) && encoder.ShortName != "copy") { return(null); } } // Find out what the real mixdown, sample rate and bitrate will be. HBMixdown mixdown; int sampleRate, bitrate; if (encoder.ShortName == "copy") { if (this.CopyMaskChoices.Any( choice => { if (!choice.Enabled) { return(false); } return((HandBrakeEncoderHelpers.GetAudioEncoder("copy:" + choice.Codec).Id & inputTrack.Codec) > 0); })) { return(outputPreviewTrack); } if (this.Profile.AudioEncoderFallback == null) { encoder = HandBrakeEncoderHelpers.AudioEncoders.First(a => !a.IsPassthrough); } else { encoder = HandBrakeEncoderHelpers.GetAudioEncoder(this.Profile.AudioEncoderFallback); } mixdown = HandBrakeEncoderHelpers.GetDefaultMixdown(encoder, (ulong)inputTrack.ChannelLayout); sampleRate = 0; bitrate = 0; outputPreviewTrack.Encoder = encoder.DisplayName; } else { mixdown = audioVM.SelectedMixdown.Mixdown; sampleRate = audioVM.SampleRate; bitrate = audioVM.SelectedBitrate.Bitrate; } HBMixdown previewMixdown; previewMixdown = HandBrakeEncoderHelpers.SanitizeMixdown(mixdown, encoder, (ulong)inputTrack.ChannelLayout); int previewSampleRate = sampleRate; if (previewSampleRate == 0) { previewSampleRate = inputTrack.SampleRate; } int previewBitrate = bitrate; if (previewBitrate == 0) { previewBitrate = HandBrakeEncoderHelpers.GetDefaultBitrate(encoder, previewSampleRate, previewMixdown); } else { previewBitrate = HandBrakeEncoderHelpers.SanitizeAudioBitrate(previewBitrate, encoder, previewSampleRate, previewMixdown); } outputPreviewTrack.Mixdown = previewMixdown.DisplayName; outputPreviewTrack.SampleRate = DisplayConversions.DisplaySampleRate(previewSampleRate); if (audioVM.EncodeRateType == AudioEncodeRateType.Bitrate) { if (previewBitrate >= 0) { outputPreviewTrack.Quality = previewBitrate + " kbps"; } else { outputPreviewTrack.Quality = string.Empty; } } else { outputPreviewTrack.Quality = "CQ " + audioVM.AudioQuality; } var modifiers = new List <string>(); if (audioVM.Gain != 0) { modifiers.Add(string.Format("{0}{1} dB", audioVM.Gain > 0 ? "+" : string.Empty, audioVM.Gain)); } if (audioVM.Drc != 0) { modifiers.Add("DRC " + audioVM.Drc.ToString()); } outputPreviewTrack.Modifiers = string.Join(", ", modifiers); return(outputPreviewTrack); }