diff options
Diffstat (limited to 'win/CS/HandBrakeWPF/Model/Audio/AudioBehaviourTrack.cs')
-rw-r--r-- | win/CS/HandBrakeWPF/Model/Audio/AudioBehaviourTrack.cs | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/win/CS/HandBrakeWPF/Model/Audio/AudioBehaviourTrack.cs b/win/CS/HandBrakeWPF/Model/Audio/AudioBehaviourTrack.cs new file mode 100644 index 000000000..b775c06b7 --- /dev/null +++ b/win/CS/HandBrakeWPF/Model/Audio/AudioBehaviourTrack.cs @@ -0,0 +1,598 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AudioTrack.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Model of a HandBrake Audio Track and it's associated behaviours. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Model.Audio +{ + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + + using HandBrake.ApplicationServices.Interop; + using HandBrake.ApplicationServices.Interop.Model; + using HandBrake.ApplicationServices.Interop.Model.Encoding; + + using Services.Encode.Model.Models; + using Utilities; + + using Newtonsoft.Json; + + /// <summary> + /// Model of a HandBrake Audio Track and it's associated behaviours. + /// </summary> + public class AudioBehaviourTrack : PropertyChangedBase + { + private int bitrate; + private double drc; + private AudioEncoder encoder; + private int gain; + private HBMixdown mixDown; + private double sampleRate; + private bool isDefault; + private IEnumerable<int> bitrates; + private IEnumerable<double> encoderQualityValues; + private AudioEncoderRateType encoderRateType; + private double? quality; + + /// <summary> + /// Initializes a new instance of the <see cref = "AudioTrack" /> class. + /// </summary> + public AudioBehaviourTrack() + { + // Default Values + this.Encoder = AudioEncoder.ffaac; + this.MixDown = HandBrakeEncoderHelpers.Mixdowns.FirstOrDefault(m => m.ShortName == "dpl2"); + this.SampleRate = 48; + this.Bitrate = 160; + this.DRC = 0; + this.EncoderRateType = AudioEncoderRateType.Bitrate; + this.SetupLimits(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="AudioTrack"/> class. + /// Copy Constructor + /// </summary> + /// <param name="track"> + /// The track. + /// </param> + public AudioBehaviourTrack(AudioBehaviourTrack track) + { + this.bitrate = track.Bitrate; + this.drc = track.DRC; + this.encoder = track.Encoder; + this.gain = track.Gain; + this.mixDown = track.MixDown; + this.sampleRate = track.SampleRate; + this.Quality = track.Quality; + this.encoderRateType = track.EncoderRateType; + this.SetupLimits(); + } + + #region Track Properties + + /// <summary> + /// Gets or sets Dynamic Range Compression + /// </summary> + public double DRC + { + get + { + return this.drc; + } + + set + { + if (!Equals(value, this.drc)) + { + this.drc = value; + this.NotifyOfPropertyChange(() => this.DRC); + } + } + } + + /// <summary> + /// Gets or sets the Gain for the audio track + /// </summary> + public int Gain + { + get + { + return this.gain; + } + + set + { + if (!Equals(value, this.gain)) + { + this.gain = value; + this.NotifyOfPropertyChange(() => this.Gain); + } + } + } + + /// <summary> + /// Gets or sets Audio Mixdown (ShortName) + /// </summary> + public HBMixdown MixDown + { + get + { + return this.IsPassthru ? null : this.mixDown; + } + + set + { + if (!object.Equals(this.mixDown, value)) + { + this.mixDown = value; + this.NotifyOfPropertyChange(() => this.MixDown); + this.SetupLimits(); + } + } + } + + /// <summary> + /// Gets or sets Audio Encoder + /// </summary> + public AudioEncoder Encoder + { + get + { + return this.encoder; + } + + set + { + if (object.Equals(this.encoder, value)) + { + return; + } + + this.encoder = value; + this.NotifyOfPropertyChange(() => this.Encoder); + this.NotifyOfPropertyChange(() => this.IsPassthru); + this.NotifyOfPropertyChange(() => this.IsBitrateVisible); + this.NotifyOfPropertyChange(() => this.IsQualityVisible); + this.NotifyOfPropertyChange(() => this.IsRateTypeVisible); + this.NotifyOfPropertyChange(() => this.TrackReference); + this.GetDefaultMixdownIfNull(); + this.SetupLimits(); + + // Refresh the available encoder rate types. + this.NotifyOfPropertyChange(() => this.AudioEncoderRateTypes); + if (!this.AudioEncoderRateTypes.Contains(this.EncoderRateType)) + { + this.EncoderRateType = AudioEncoderRateType.Bitrate; // Default to bitrate. + } + } + } + + /// <summary> + /// Gets or sets Audio SampleRate + /// </summary> + public double SampleRate + { + get + { + return this.sampleRate; + } + + set + { + this.sampleRate = value; + this.NotifyOfPropertyChange(() => this.SampleRate); + this.SetupLimits(); + } + } + + /// <summary> + /// Gets or sets the encoder rate type. + /// </summary> + public AudioEncoderRateType EncoderRateType + { + get + { + return this.encoderRateType; + } + + set + { + this.encoderRateType = value; + this.SetupLimits(); + this.NotifyOfPropertyChange(() => this.EncoderRateType); + this.NotifyOfPropertyChange(() => this.IsBitrateVisible); + this.NotifyOfPropertyChange(() => this.IsQualityVisible); + + if (!this.Quality.HasValue) + { + HBAudioEncoder hbAudioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(this.Encoder)); + this.Quality = HandBrakeEncoderHelpers.GetDefaultQuality(hbAudioEncoder); + } + } + } + + /// <summary> + /// Gets or sets Audio Bitrate + /// </summary> + public int Bitrate + { + get + { + return this.bitrate; + } + + set + { + this.bitrate = value; + this.NotifyOfPropertyChange(() => this.Bitrate); + } + } + + /// <summary> + /// Gets or sets Audio quality + /// </summary> + public double? Quality + { + get + { + return this.quality; + } + + set + { + this.quality = value; + this.NotifyOfPropertyChange(() => this.quality); + } + } + + #endregion + + /// <summary> + /// Gets AudioEncoderDisplayValue. + /// </summary> + [JsonIgnore] + public string AudioEncoderDisplayValue + { + get + { + return EnumHelper<AudioEncoder>.GetDisplay(this.Encoder); + } + } + + /// <summary> + /// Gets the The UI display value for bit rate + /// </summary> + [JsonIgnore] + public string BitRateDisplayValue + { + get + { + if (this.Encoder == AudioEncoder.Ac3Passthrough || this.Encoder == AudioEncoder.DtsPassthrough + || this.Encoder == AudioEncoder.DtsHDPassthrough) + { + return "Auto"; + } + + return this.Bitrate.ToString(); + } + } + + /// <summary> + /// Gets or sets a value indicating whether is default. + /// TODO - Can this be removed? May have been added as a quick fix for a styling quirk. + /// </summary> + [JsonIgnore] + public bool IsDefault + { + get + { + return this.isDefault; + } + set + { + this.isDefault = value; + } + } + + /// <summary> + /// Gets or sets the The UI display value for sample rate + /// </summary> + [JsonIgnore] + public string SampleRateDisplayValue + { + get + { + return this.SampleRate == 0 ? "Auto" : this.SampleRate.ToString(CultureInfo.InvariantCulture); + } + set + { + // TODO change this to be a converted field + if (string.IsNullOrEmpty(value)) + { + return; + } + + double samplerate; + double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out samplerate); + + this.SampleRate = samplerate; + } + } + + /// <summary> + /// Gets a value indicating whether IsPassthru. + /// </summary> + [JsonIgnore] + public bool IsPassthru + { + get + { + if (this.Encoder == AudioEncoder.Ac3Passthrough || this.Encoder == AudioEncoder.DtsPassthrough + || this.Encoder == AudioEncoder.DtsHDPassthrough || this.Encoder == AudioEncoder.AacPassthru + || this.Encoder == AudioEncoder.Mp3Passthru || this.Encoder == AudioEncoder.Passthrough || + this.Encoder == AudioEncoder.EAc3Passthrough || this.Encoder == AudioEncoder.TrueHDPassthrough + || this.Encoder == AudioEncoder.FlacPassthru) + { + return true; + } + return false; + } + } + + /// <summary> + /// Gets the bitrates. + /// </summary> + [JsonIgnore] + public IEnumerable<int> Bitrates + { + get + { + return this.bitrates; + } + } + + /// <summary> + /// Gets the quality compression values. + /// </summary> + [JsonIgnore] + public IEnumerable<double> EncoderQualityValues + { + get + { + return this.encoderQualityValues; + } + } + + /// <summary> + /// Gets the audio encoder rate types. + /// </summary> + [JsonIgnore] + public IEnumerable<AudioEncoderRateType> AudioEncoderRateTypes + { + get + { + IList<AudioEncoderRateType> types = EnumHelper<AudioEncoderRateType>.GetEnumList().ToList(); + HBAudioEncoder hbaenc = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(this.Encoder)); + if (hbaenc == null || !hbaenc.SupportsQuality) + { + types.Remove(AudioEncoderRateType.Quality); + } + + return types; + } + } + + /// <summary> + /// Gets a value indicating whether can set bitrate. + /// </summary> + [JsonIgnore] + public bool IsBitrateVisible + { + get + { + if (this.IsPassthru || this.Encoder == AudioEncoder.ffflac || this.Encoder == AudioEncoder.ffflac24) + { + return false; + } + + return Equals(this.EncoderRateType, AudioEncoderRateType.Bitrate); + } + } + + /// <summary> + /// Gets a value indicating whether is quality visible. + /// </summary> + [JsonIgnore] + public bool IsQualityVisible + { + get + { + if (this.IsPassthru || this.Encoder == AudioEncoder.ffflac || this.Encoder == AudioEncoder.ffflac24) + { + return false; + } + + return Equals(this.EncoderRateType, AudioEncoderRateType.Quality); + } + } + + /// <summary> + /// Gets a value indicating whether is rate type visible. + /// </summary> + [JsonIgnore] + public bool IsRateTypeVisible + { + get + { + if (this.IsPassthru || this.Encoder == AudioEncoder.ffflac || this.Encoder == AudioEncoder.ffflac24) + { + return false; + } + + return true; + } + } + + /// <summary> + /// Gets a value indicating whether IsLossless. + /// </summary> + [JsonIgnore] + public bool IsLossless + { + get + { + return this.IsPassthru || this.Encoder == AudioEncoder.ffflac || this.Encoder == AudioEncoder.ffflac24; + } + } + + /// <summary> + /// Gets TrackReference. + /// </summary> + [JsonIgnore] + public AudioBehaviourTrack TrackReference + { + get { return this; } + } + + #region Handler Methods + + /// <summary> + /// The setup limits. + /// </summary> + private void SetupLimits() + { + this.SetupBitrateLimits(); + this.SetupQualityCompressionLimits(); + } + + /// <summary> + /// The calculate bitrate limits. + /// </summary> + private void SetupBitrateLimits() + { + // Base set of bitrates available. + List<int> audioBitrates = HandBrakeEncoderHelpers.AudioBitrates; + + // Defaults + int max = 256; + int low = 32; + + // Based on the users settings, find the high and low bitrates. + HBAudioEncoder hbaenc = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(this.Encoder)); + HBRate rate = HandBrakeEncoderHelpers.AudioSampleRates.FirstOrDefault(t => t.Name == this.SampleRate.ToString(CultureInfo.InvariantCulture)); + HBMixdown mixdown = this.mixDown ?? HandBrakeEncoderHelpers.GetMixdown("dpl2"); + + BitrateLimits limits = HandBrakeEncoderHelpers.GetBitrateLimits(hbaenc, rate != null ? rate.Rate : 48000, mixdown); + if (limits != null) + { + max = limits.High; + low = limits.Low; + } + + // Return the subset of available bitrates. + List<int> subsetBitrates = audioBitrates.Where(b => b <= max && b >= low).ToList(); + this.bitrates = subsetBitrates; + this.NotifyOfPropertyChange(() => this.Bitrates); + + // If the subset does not contain the current bitrate, request the default. + if (!subsetBitrates.Contains(this.Bitrate)) + { + this.Bitrate = HandBrakeEncoderHelpers.GetDefaultBitrate(hbaenc, rate != null ? rate.Rate : 48000, mixdown); + } + } + + /// <summary> + /// The setup quality compression limits. + /// </summary> + private void SetupQualityCompressionLimits() + { + HBAudioEncoder hbAudioEncoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(this.Encoder)); + if (hbAudioEncoder.SupportsQuality) + { + RangeLimits limits = null; + + if (hbAudioEncoder.SupportsQuality) + { + limits = hbAudioEncoder.QualityLimits; + } + + if (limits != null) + { + double value = limits.Ascending ? limits.Low : limits.High; + List<double> values = new List<double> { value }; + + if (limits.Ascending) + { + while (value < limits.High) + { + value += limits.Granularity; + values.Add(value); + } + } + else + { + while (value > limits.Low) + { + value -= limits.Granularity; + values.Add(value); + } + } + + this.encoderQualityValues = values; + } + else + { + this.encoderQualityValues = new List<double>(); + } + } + else + { + this.encoderQualityValues = new List<double>(); + } + + // Default the audio quality value if it's out of range. + if (Equals(this.EncoderRateType, AudioEncoderRateType.Quality)) + { + if (this.Quality.HasValue && !this.encoderQualityValues.Contains(this.Quality.Value)) + { + this.Quality = HandBrakeEncoderHelpers.GetDefaultQuality(hbAudioEncoder); + } + } + + this.NotifyOfPropertyChange(() => this.EncoderQualityValues); + } + + /// <summary> + /// Set the default mixdown when the mixdown is null or "none" + /// </summary> + private void GetDefaultMixdownIfNull() + { + //if (this.ScannedTrack == null) + //{ + // return; + //} + + //HBAudioEncoder aencoder = HandBrakeEncoderHelpers.GetAudioEncoder(EnumHelper<AudioEncoder>.GetShortName(this.encoder)); + //HBMixdown currentMixdown = HandBrakeEncoderHelpers.GetMixdown(this.mixDown); + //HBMixdown sanitisedMixdown = HandBrakeEncoderHelpers.SanitizeMixdown(currentMixdown, aencoder, (uint)this.ScannedTrack.ChannelLayout); + //HBMixdown defaultMixdown = HandBrakeEncoderHelpers.GetDefaultMixdown(aencoder, (uint)this.ScannedTrack.ChannelLayout); + + //if (this.mixDown == null || this.mixDown == "none") + //{ + // this.MixDown = defaultMixdown.ShortName; + //} + //else if (sanitisedMixdown != null) + //{ + // this.MixDown = sanitisedMixdown.ShortName; + //} + } + + #endregion + } +}
\ No newline at end of file |