/// <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));
 }
Example #4
0
 /// <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);
 }
Example #5
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);
        }
Example #6
0
        /// <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));
        }
Example #7
0
 /// <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));
 }
Example #8
0
 /// <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);
 }
Example #9
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);
        }
Example #10
0
        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);
        }
Example #12
0
        /// <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);
 }
Example #14
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);
        }
Example #15
0
 /// <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;
        }
Example #17
0
        /// <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);
 }
Example #19
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));
 }
Example #23
0
 /// <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);
 }
Example #24
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);
        }