using DTS.Common.Enums.Hardware; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace DTS.Common.Classes.DSP { /// /// see IStreamingFilterProfile for more information /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Acronym")] public class DSPFilterType : IStreamingFilterProfile { public double Ratio { get; set; } public int EnumValue { get; set; } public string DisplayString { get; set; } public string DescriptionString { get; set; } private readonly List _restrictions = new List(); public DASRestriction[] Restrictions { get => _restrictions.ToArray(); set { _restrictions.Clear(); _restrictions.AddRange(value); } } public DSPFilterType() { } public DSPFilterType(DSPFilterCollection.DSPFilterDefaults filter, DASRestriction[] restrictions) { GetProfileValues(filter, out var displayName, out var description, out var enumValue, out var ratio); Initialize(enumValue, displayName, description, ratio, restrictions); } public DSPFilterType(int enumValue, string displayString, string descriptionString, double ratio, DASRestriction[] restrictions) { Initialize(enumValue, displayString, descriptionString, ratio, restrictions); } private void Initialize(int enumValue, string displayString, string descriptionString, double ratio, DASRestriction[] restrictions) { EnumValue = enumValue; DisplayString = displayString; DescriptionString = descriptionString; Restrictions = restrictions; Ratio = ratio; } public override string ToString() { return DisplayString; } public static void GetProfileValues(DSPFilterCollection.DSPFilterDefaults filter, out string displayName, out string description, out int enumValue, out double ratio) { displayName = string.Empty; description = string.Empty; enumValue = -1; ratio = -1; var enumType = typeof(DSPFilterCollection.DSPFilterDefaults); var memberInfos = enumType.GetMember(filter.ToString()); var enumValueMemberInfo = Array.Find(memberInfos, m => m.DeclaringType == enumType); var valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(DisplayAttribute), false); enumValue = (int)filter; description = ((DisplayAttribute)valueAttributes[0]).GetDescription(); displayName = ((DisplayAttribute)valueAttributes[0]).GetName(); valueAttributes = enumValueMemberInfo.GetCustomAttributes(typeof(ScalerAttribute), false); ratio = ((ScalerAttribute)valueAttributes[0]).Scaler; } /// /// this is the table of breakpoints and corresponding fC for S6A/br /// private static readonly List> _6PButterWorthTable = new List> ( new[] { new Tuple(8000, 1280), new Tuple(5000, 610), new Tuple(2000, 366), new Tuple(1000, 120), new Tuple(500,120), new Tuple(200,50), new Tuple(80,15) } ); /// /// returns an array of breakpoints and fC for S6A and S6A-BR legacy butterworth digital filter /// /// public static Tuple[] Get6PButterWorthLegacyTable() { return _6PButterWorthTable.ToArray(); } /// /// this is the cap of SPS where S6A will fall back on AAF /// public const int S6A_CAP = 20480; /// /// returns the fC given a hardware type, and the legacy 6P butterworth filter /// double.NaN means the filter is not supported /// /// /// /// public static double GetLegacytDSPFilterRate(double sps, string hwType) { //if we have legacy then we need the sample rate, if it's >8k s6abr then Fc if (hwType == HardwareTypes.SLICE6_AIR.ToString() && sps >= S6A_CAP) { return double.NaN; } var array = Get6PButterWorthLegacyTable(); Array.Sort(array, (x, y) => { return y.Item1.CompareTo(x.Item1); }); foreach (var entry in array) { if (sps >= entry.Item1) { return entry.Item2; } } return double.NaN; } /// /// returns a filter rate given the current digital filter profile and sps and hardware type /// /// /// /// public double GetDSPFilterRate(double sps, string hwType) { if (EnumValue != DSPFilterCollection.BUTTERWORTH) { return double.NaN; } if (!Array.Exists(Restrictions, x => x.DASType == hwType || string.IsNullOrEmpty(x.DASType))) { return double.NaN; } return GetLegacytDSPFilterRate(sps, hwType); } } }