public PeqDataViewModel NewParam() { if (RequiredBiquads <= (int)(DataModel.SpeakerPeqType)) { var dm = new PeqDataModel { Frequency = 1000, FilterType = FilterType.Peaking, IsEnabled = true, BandWidth = 1, Boost = 0, Order = 2, Id = PeqDataModels.Count }; //vms might not be initiated, add viewmodel before model as initialisation wraps all available models var vm = new PeqDataViewModel(dm); PeqDataViewModels.Add(vm); PeqDataModels.Add(dm); var sl = new SpeakerLogic(DataModel); sl.AssignBiquads(dm); return(vm); } throw new Exception("not enough biquads"); }
private FilterLogicBase LogicFactory(PeqDataModel model) { switch (model.FilterType) { case FilterType.Peaking: return(new PeakingLogic(model, Model, _flowId)); default: return(new CrossoverLogic(model, Model, _flowId)); } }
public PeqDataViewModel(PeqDataModel peq) { PeqDataModel = peq; if (PeqDataModel.BandWidth < MinBandWidth) { PeqDataModel.BandWidth = MinBandWidth; } if (PeqDataModel.Frequency < MinFreq) { PeqDataModel.Frequency = MinFreq; } DraggablePoint.PositionCoerceCallbacks.Add((container, position) => { var point = position; if (Math.Abs(point.Y - 0) > .1 && FilterType != FilterType.Peaking && FilterType != FilterType.LowShelf && FilterType != FilterType.HighShelf) { point = new Point(point.X, 0); } if (point.X > 20000) { point = new Point(20000, point.Y); } if (point.Y > 15) { point = new Point(point.X, 15); } if (point.X < 10) { point = new Point(10, point.Y); } if (point.Y < -15) { point = new Point(point.X, -15); } return(point); }); DraggablePoint.PositionChanged += (sender, e) => { if ((Math.Abs(Math.Log10(e.Position.X) - Math.Log10(Frequency)) < .05) && (Math.Abs(e.Position.Y - Boost) < 0.2)) { return; } Frequency = e.Position.X; Boost = e.Position.Y; }; }
/// <summary> /// Resolves redundant peq blocks /// </summary> /// <param name="input">Array representing the redundancy data</param> /// <returns>PeqDatamodel with all settings except used biquads</returns> public void Parse(byte[] input) { if ((input == null) || (input.Length != PeqRedundancyCount)) { throw new ArgumentException("no data found in this peq data"); } double b = BitConverter.ToUInt16(new[] { input[0], input[1] }, 0); var peqDataModel = new PeqDataModel { Frequency = Math.Pow(10, b / FreqDevider), Order = input[2] & 0x07, FilterType = (FilterType)(input[2] >> 3 & 0x0F), IsEnabled = (input[2] >> 7 & 0x01) > 0, BandWidth = input[3] / 36.0, Boost = (input[4] - 0x80) / 5.0, Gain = (input[5] - 0x80) / 5.0 }; var dspBq = new List <int> { (byte)(input[6] & 0x0F), (byte)((input[6] & 0xF0) >> 4), (byte)(input[7] & 0x0F), (byte)((input[7] & 0xF0) >> 4) }; peqDataModel.Biquads = new List <int>(dspBq.Where(q => q != 15)); if (peqDataModel.Frequency < 10 || peqDataModel.Frequency > 20000 || peqDataModel.Order < 1 || peqDataModel.Order > 6 || (int)peqDataModel.FilterType < 0 || (int)peqDataModel.FilterType > 7 || peqDataModel.BandWidth < .1 || peqDataModel.BandWidth > 7 || peqDataModel.Boost < -15 || peqDataModel.Boost > 15 || peqDataModel.Gain < -15 || peqDataModel.Gain > 15) { throw new ArgumentException("the eq data found is not applicable"); } PEQDataModel.BandWidth = peqDataModel.BandWidth; PEQDataModel.Biquads = peqDataModel.Biquads; PEQDataModel.Boost = peqDataModel.Boost; PEQDataModel.FilterType = peqDataModel.FilterType; PEQDataModel.Frequency = peqDataModel.Frequency; PEQDataModel.Gain = peqDataModel.Gain; PEQDataModel.IsEnabled = peqDataModel.IsEnabled; PEQDataModel.Order = peqDataModel.Order; }
protected FilterLogicBase(PeqDataModel peqDataModel, SpeakerDataModel model, int flowId) : base(peqDataModel) { _model = model; FlowId = flowId; if (PEQDataModel.Biquads == null) { throw new Exception("No biquads are defined for this filter"); } if (new[] { PEQDataModel }.RequiredBiquads() > PEQDataModel.Biquads.Count) { throw new Exception("Not enough biquads are defined for this filter"); } }
private static PeqDataModel TestPeqParam(FilterType filterType, int freq, int order) { var peqdata0 = new PeqDataModel { BandWidth = 1, Boost = 1, Biquads = null, FilterType = filterType, Frequency = freq, Gain = 1, IsEnabled = true, Order = order }; return(peqdata0); }
public void AssignBiquads(PeqDataModel dm) { var r = new[] { dm }.RequiredBiquads(); var availablebq = AvailableBiquads(); foreach (var biquad in dm.Biquads) { availablebq.Push(biquad); } dm.Biquads = new List <int>(); for (int i = 0; i < r; i++) { dm.Biquads.Add(availablebq.Pop()); } }
private void SetPeqData(byte[] rawData) { if (rawData.All(s => s == 0)) { return; } try { var pdm = new PeqDataModel(); var fb = new FilterBase(pdm); fb.Parse(rawData); Model.PEQ.Add(pdm); } catch (ArgumentException a) { Debug.WriteLine("Raw eeprom data could not be parsed for peq " + a); return; } }
private void SendParamData(PeqDataModel dm) { if (!_flowId.HasValue) { return; } try { var sl = new SpeakerLogicForFlow(DataModel, _flowId.Value); var data = sl.DspData(dm); var redundancy = sl.RedundancyData(); CommunicationViewModel.AddData(redundancy); CommunicationViewModel.AddData(data); } catch (Exception e) { MessageBox.Show(e.Message, "Filter upload", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); } }
private void AddNew(PeqDataModel data) { var dm = new PeqDataModel { Id = PeqDataModels.Count, FilterType = data.FilterType, IsEnabled = data.IsEnabled, BandWidth = data.BandWidth, Boost = data.Boost, Frequency = data.Frequency, Order = data.Order, Gain = data.Gain, }; //dm.Parse(data); PeqDataModels.Add(dm); var vm = new PeqDataViewModel(dm); vm.RemoveThisParam += RemovePeqParam; PeqDataViewModels.Add(vm); }
public void RedundancyCheck() { foreach (var q in TestSpeaker().PEQ) { var z = new FilterBase(q); var data = z.RedundancyToBytes(); var conv = new PeqDataModel(); var logic = new FilterBase(conv); logic.Parse(data); Assert.AreEqual(q.Frequency, conv.Frequency, .5); Assert.AreEqual(q.Boost, conv.Boost, .5); Assert.AreEqual(q.Gain, conv.Gain, .5); Assert.AreEqual(q.FilterType, conv.FilterType); Assert.AreEqual(q.IsEnabled, conv.IsEnabled); Assert.AreEqual(q.BandWidth, conv.BandWidth, .5); Assert.AreEqual(q.Order, conv.Order); CollectionAssert.AreEqual(q.Biquads.ToArray(), conv.Biquads.ToArray()); } }
private static Complex Butterworth(double f, PeqDataModel data, int order, bool isHighPass) { var order1 = order == 0 ? data.Order : order; var rads = f.W(); var wc = data.Frequency.W(); var s = isHighPass ? new Complex(0, wc / rads) : new Complex(0, rads / wc); switch (order1) { case 1: return 1 / (s + 1); case 2: return 1 / (Complex.Pow(s, 2) + 1.4142 * s + 1); case 3: return 1 / ((s + 1) * (Complex.Pow(s, 2) + s + 1)); case 4: return 1 / ((Complex.Pow(s, 2) + 0.7654 * s + 1) * (Complex.Pow(s, 2) + 1.8478 * s + 1)); case 5: return 1 / ((s + 1) * (Complex.Pow(s, 2) + 0.6180 * s + 1) * (Complex.Pow(s, 2) + 1.6180 * s + 1)); case 6: return 1 / ((Complex.Pow(s, 2) + .5176 * s + 1) * (Complex.Pow(s, 2) + 1.4142 * s + 1) * (Complex.Pow(s, 2) + 1.9319 * s + 1)); default: return 1; } }
private static Complex Shelf(double f, PeqDataModel data, bool isHigh) { var rads = f.W(); var a = data.Boost.A(); var q = data.BandWidth.Q(); var wc = data.Frequency.W(); var s = new Complex(0, rads / wc); var s2 = Complex.Pow(s, 2); return isHigh ? (a * a * s2 + (Math.Sqrt(a) / q) * s + 1) / (s2 + (Math.Sqrt(a) / q) * s + a) : (a * s2 + (Math.Sqrt(a) / q) * s + a) / (a * s2 + (Math.Sqrt(a) / q) * s + 1); }
/// <summary> /// Peaking filter /// </summary> /// <returns> magnitude and fase for freqency </returns> private static Complex Peaking(double f, PeqDataModel data) { var rads = f.W(); var a = data.Boost.A(); var q = data.BandWidth.Q(); var wc = data.Frequency.W(); var s = new Complex(0, wc / rads); return (Complex.Pow(s, 2) + a * s / q + 1) / (Complex.Pow(s, 2) + (s / (a * q)) + 1); }
private static Complex Notch(double f, PeqDataModel data) { var rads = f.W(); var wc = data.Frequency.W(); var s = new Complex(0, rads / wc); var s2 = Complex.Pow(s, 2); return (s2 + 1) / (s2 + (s / data.BandWidth.Q()) + 1); }
private static Complex LowShelf(double f, PeqDataModel data) { return Shelf(f, data, false); }
private static Complex LinkWitzLp(double f, PeqDataModel data) { return LinkWitz(f, data, false); }
public FilterBase(PeqDataModel model) { PEQDataModel = model; }
/// <summary> /// Get redundancy data for specific parameter /// </summary> /// <param name="data"></param> /// <returns></returns> public IEnumerable <SetE2PromExt> Redundancy(PeqDataModel data) { return(LogicFactory(data).RedundancyData()); }
private static Complex BesselLp(double f, PeqDataModel data) { return Bessel(f, data, false); }
private static Complex BesselHp(double f, PeqDataModel data) { return Bessel(f, data, true); }
private static Complex Bessel(double f, PeqDataModel data, bool isHighPass) { var rads = f.W(); var wc = data.Frequency.W(); var s = isHighPass ? new Complex(0, wc / rads) : new Complex(0, rads / wc); switch (data.Order) { case 1: return 1 / (s + 1); case 2: return 1 / (Complex.Pow(s, 2) + 1.7321 * s + 1); case 3: return 1 / (Complex.Pow(s, 3) + Complex.Pow(s, 2) * 2.4329 + s * 2.4662 + 1); case 4: return 1 / (Complex.Pow(s, 4) + Complex.Pow(s, 3) * 3.1239 + Complex.Pow(s, 2) * 4.3916 + 3.2011 * s + 1); case 5: return 1 / (Complex.Pow(s, 5) + Complex.Pow(s, 4) * 3.8107 + Complex.Pow(s, 3) * 6.7767 + Complex.Pow(s, 2) * 6.8864 + 3.9363 * s + 1); case 6: return 1 / (Complex.Pow(s, 6) + Complex.Pow(s, 5) * 4.4952 + Complex.Pow(s, 4) * 9.6223 + Complex.Pow(s, 3) * 12.3583 + Complex.Pow(s, 2) * 9.9202 + 4.6717 * s + 1); default: return 1; } }
public PeakingLogic(PeqDataModel peqDataModel, SpeakerDataModel model, int flowId) : base(peqDataModel, model, flowId) { }
private static Complex ButterworthLp(double f, PeqDataModel data) { return Butterworth(f, data, 0, false); }
/// <summary> /// Get dsp data for specific parameter /// </summary> /// <param name="data"></param> /// <returns></returns> public IEnumerable <PeqParam> DspData(PeqDataModel data) { return(LogicFactory(data).GetParamData()); }
private static Complex HighShelf(double f, PeqDataModel data) { return Shelf(f, data, true); }
public CrossoverLogic(PeqDataModel peqDataModel, SpeakerDataModel model, int flowId) : base(peqDataModel, model, flowId) { }
/// <summary> /// 12 dB/oct = 2 cascaded 1st order butterworths (2 biquads) 2ND /// 24 dB/oct = 2 cascaded 2nd order butterworths (2 biquads) 4TH /// 36 dB/oct = 2 cascaded 3rd order butterworths 6TH /// 48 dB/oct = 2 cascaded 4th order butterworths 8TH /// </summary> private static Complex LinkWitz(double f, PeqDataModel data, bool isHighPass) { if (data.Order % 2 != 0) return 0; var bf = Butterworth(f, data, data.Order >> 1, isHighPass); return Complex.Pow(bf, 2); }
private static Complex LinkWitzHp(double f, PeqDataModel data) { return LinkWitz(f, data, true); }
public PeakingFilter(PeqDataModel peq) : base(peq) { }