diff --git a/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSet.cs b/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSet.cs index f4c4ba67..ea2471f8 100644 --- a/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSet.cs +++ b/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSet.cs @@ -103,6 +103,7 @@ public static FilterSet Create(FilterSetTarget device, int channels, int sampleR FilterSetTarget.MultEQXRaw => new MultEQXRawFilterSet(channels, sampleRate), FilterSetTarget.MultEQXTarget => new MultEQXTargetFilterSet(channels, sampleRate), FilterSetTarget.YPAO => new YPAOFilterSet(channels, sampleRate), + FilterSetTarget.YPAOLite => new YPAOLiteFilterSet(channels, sampleRate), _ => throw new NotSupportedException() }; } @@ -137,6 +138,7 @@ public static FilterSet Create(FilterSetTarget device, ReferenceChannel[] channe FilterSetTarget.MultEQXRaw => new MultEQXRawFilterSet(channels, sampleRate), FilterSetTarget.MultEQXTarget => new MultEQXTargetFilterSet(channels, sampleRate), FilterSetTarget.YPAO => new YPAOFilterSet(channels, sampleRate), + FilterSetTarget.YPAOLite => new YPAOLiteFilterSet(channels, sampleRate), _ => throw new NotSupportedException() }; } diff --git a/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSetTarget.cs b/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSetTarget.cs index 2ea54f61..1b83e8e7 100644 --- a/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSetTarget.cs +++ b/Cavern.QuickEQ.Format/FilterSet/BaseClasses/FilterSetTarget.cs @@ -123,6 +123,10 @@ public enum FilterSetTarget { /// Processors supporting the latest YPAO with additional fine tuning PEQs. /// YPAO, + /// + /// Older Yamaha processors with fixed 7 bands. + /// + YPAOLite, } /// @@ -161,7 +165,8 @@ public static class FilterSetTargetExtensions { FilterSetTarget.MultEQX => "MultEQ-X - MQX file", FilterSetTarget.MultEQXRaw => "MultEQ-X - Peaking EQ", FilterSetTarget.MultEQXTarget => "MultEQ-X - Filter curves", - FilterSetTarget.YPAO => "YPAO", + FilterSetTarget.YPAO => "YPAO - free bands", + FilterSetTarget.YPAOLite => "YPAO - fixed bands", _ => throw new NotSupportedException() }; } diff --git a/Cavern.QuickEQ.Format/FilterSet/DiracLiveBassControlFilterSet.cs b/Cavern.QuickEQ.Format/FilterSet/DiracLiveBassControlFilterSet.cs index 0d0074c9..ea325ec6 100644 --- a/Cavern.QuickEQ.Format/FilterSet/DiracLiveBassControlFilterSet.cs +++ b/Cavern.QuickEQ.Format/FilterSet/DiracLiveBassControlFilterSet.cs @@ -68,14 +68,20 @@ public override void Export(string path) { } } + /// + /// Extracted channel pairs are for memory optimization. + /// + static readonly (string name, ReferenceChannel[] channels) + fronts = ("Fronts", new[] { ReferenceChannel.FrontLeft, ReferenceChannel.FrontRight }), + wides = ("Wide Surrounds", new[] { ReferenceChannel.WideLeft, ReferenceChannel.WideRight }), + sides = ("Side Surrounds", new[] { ReferenceChannel.SideLeft, ReferenceChannel.SideRight }), + rears = ("Rear Surrounds", new[] { ReferenceChannel.RearLeft, ReferenceChannel.RearRight }); + /// /// The channels that are combined into one EQ group for DLBC versions where the height pairs are separate groups. /// static readonly (string name, ReferenceChannel[] channels)[] groupsWithSeparateHeights = { - ("Fronts", new[] { ReferenceChannel.FrontLeft, ReferenceChannel.FrontRight }), - ("Wide Surrounds", new[] { ReferenceChannel.WideLeft, ReferenceChannel.WideRight }), - ("Side Surrounds", new[] { ReferenceChannel.SideLeft, ReferenceChannel.SideRight }), - ("Rear Surrounds", new[] { ReferenceChannel.RearLeft, ReferenceChannel.RearRight }), + fronts, wides, sides, rears, ("Front Heights", new[] { ReferenceChannel.TopFrontLeft, ReferenceChannel.TopFrontRight }), ("Side Heights", new[] { ReferenceChannel.TopSideLeft, ReferenceChannel.TopSideRight }), ("Rear Heights", new[] { ReferenceChannel.TopRearLeft, ReferenceChannel.TopRearRight }) @@ -85,10 +91,7 @@ static readonly (string name, ReferenceChannel[] channels)[] groupsWithSeparateH /// The channels that are combined into one EQ group for DLBC versions where there are no different height pair groups. /// static readonly (string name, ReferenceChannel[] channels)[] groupsWithCombinedHeights = { - ("Fronts", new[] { ReferenceChannel.FrontLeft, ReferenceChannel.FrontRight }), - ("Wide Surrounds", new[] { ReferenceChannel.WideLeft, ReferenceChannel.WideRight }), - ("Side Surrounds", new[] { ReferenceChannel.SideLeft, ReferenceChannel.SideRight }), - ("Rear Surrounds", new[] { ReferenceChannel.RearLeft, ReferenceChannel.RearRight }), + fronts, wides, sides, rears, ("Heights", new[] { ReferenceChannel.TopFrontLeft, ReferenceChannel.TopFrontCenter, ReferenceChannel.TopFrontRight, ReferenceChannel.TopSideLeft, ReferenceChannel.GodsVoice, ReferenceChannel.TopSideRight, ReferenceChannel.TopRearLeft, ReferenceChannel.TopRearCenter, ReferenceChannel.TopRearRight }), diff --git a/Cavern.QuickEQ.Format/FilterSet/MultibandPEQFilterSet.cs b/Cavern.QuickEQ.Format/FilterSet/MultibandPEQFilterSet.cs index 05be87e4..b4037ff5 100644 --- a/Cavern.QuickEQ.Format/FilterSet/MultibandPEQFilterSet.cs +++ b/Cavern.QuickEQ.Format/FilterSet/MultibandPEQFilterSet.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; +using Cavern.Channels; using Cavern.Filters; using Cavern.QuickEQ.Equalization; @@ -9,6 +10,17 @@ namespace Cavern.Format.FilterSet { /// Exports a traditional multiband eqalizer with constant bandwidth bands. /// public class MultibandPEQFilterSet : IIRFilterSet { + /// + public override double MinGain => -12; + + /// + public override double MaxGain => 6; + + /// + /// Limit the number of bands exported for the LFE channel. + /// + protected int LFEBands { get; set; } + /// /// Frequency of the first exported band. /// @@ -17,7 +29,7 @@ public class MultibandPEQFilterSet : IIRFilterSet { /// /// Number of bands for each octave. /// - readonly int bandsPerOctave; + readonly double bandsPerOctave; /// /// Number of total bands. @@ -32,11 +44,28 @@ public class MultibandPEQFilterSet : IIRFilterSet { /// Frequency of the first exported band /// Number of bands for each octave /// Number of total bands - public MultibandPEQFilterSet(int channels, int sampleRate, double firstBand, int bandsPerOctave, int bandCount) : + public MultibandPEQFilterSet(int channels, int sampleRate, double firstBand, double bandsPerOctave, int bandCount) : + base(channels, sampleRate) { + this.firstBand = firstBand; + this.bandsPerOctave = bandsPerOctave; + this.bandCount = bandCount; + LFEBands = bandCount; + } + + /// + /// Construct a traditional multiband eqalizer with constant bandwidth bands. + /// + /// Channels in the target system + /// Filter sample rate + /// Frequency of the first exported band + /// Number of bands for each octave + /// Number of total bands + public MultibandPEQFilterSet(ReferenceChannel[] channels, int sampleRate, double firstBand, double bandsPerOctave, int bandCount) : base(channels, sampleRate) { this.firstBand = firstBand; this.bandsPerOctave = bandsPerOctave; this.bandCount = bandCount; + LFEBands = bandCount; } /// @@ -44,8 +73,8 @@ public MultibandPEQFilterSet(int channels, int sampleRate, double firstBand, int /// public PeakingEQ[] CalculateFilters(Equalizer targetToReach) { PeakingEQ[] result = new PeakingEqualizer(targetToReach) { - MinGain = -12, - MaxGain = 6 + MinGain = MinGain, + MaxGain = MaxGain }.GetPeakingEQ(SampleRate, firstBand, bandsPerOctave, bandCount); IReadOnlyList bands = targetToReach.Bands; @@ -69,14 +98,16 @@ public override void Export(string path) { for (int i = 0; i < Channels.Length; i++) { IIRChannelData channelRef = (IIRChannelData)Channels[i]; result.Add(string.Empty); - result.Add(channelRef.name); - result.Add(new string('=', channelRef.name.Length)); + string chName = GetLabel(i); + result.Add(chName); + result.Add(new string('=', chName.Length)); RootFileExtension(i, result); if (channelRef.delaySamples != 0) { result.Add("Delay: " + GetDelay(i).ToString("0.00 ms")); } BiquadFilter[] bands = channelRef.filters; - for (int j = 0; j < bands.Length; j++) { + int bandc = channelRef.reference != ReferenceChannel.ScreenLFE ? bands.Length : LFEBands; + for (int j = 0; j < bandc; j++) { result.Add($"{bands[j].CenterFreq:0} Hz:\t{bands[j].Gain:0.00} dB"); } } diff --git a/Cavern.QuickEQ.Format/FilterSet/YPAOFilterSet.cs b/Cavern.QuickEQ.Format/FilterSet/YPAOFilterSet.cs index d753f24a..240c2bc3 100644 --- a/Cavern.QuickEQ.Format/FilterSet/YPAOFilterSet.cs +++ b/Cavern.QuickEQ.Format/FilterSet/YPAOFilterSet.cs @@ -7,31 +7,28 @@ namespace Cavern.Format.FilterSet { /// - /// Filter set to fine tune an existing YPAO calibration with. + /// Filter set limited to 1/3 octave band choices for some versions of YPAO. /// public class YPAOFilterSet : IIRFilterSet { - /// - /// Maximum number of peaking EQ filters per channel. - /// + /// public override int Bands => 7; - /// - /// Maximum gain of a single peaking EQ band in decibels. - /// + /// public override double MaxGain => 6; - /// - /// Round the gains to this precision. - /// + /// + public override double MinGain => -6; + + /// public override double GainPrecision => .5f; /// - /// Filter set to fine tune an existing YPAO calibration with. + /// Filter set limited to 1/3 octave band choices for some versions of YPAO. /// public YPAOFilterSet(int channels, int sampleRate) : base(channels, sampleRate) { } /// - /// Filter set to fine tune an existing YPAO calibration with. + /// Filter set limited to 1/3 octave band choices for some versions of YPAO. /// public YPAOFilterSet(ReferenceChannel[] channels, int sampleRate) : base(channels, sampleRate) { } @@ -46,7 +43,7 @@ public override void Export(string path) { BiquadFilter[] filters = ((IIRChannelData)Channels[i]).filters; for (int j = 0; j < filters.Length;) { BiquadFilter filter = filters[j]; - result.Add($"Filter {++j} - Frequency: {bands.Nearest((float)filter.CenterFreq)}, Q factor: " + + result.Add($"Filter {++j} - Frequency: {frequencies.Nearest((float)filter.CenterFreq)}, Q factor: " + $"{qFactors.Nearest((float)filter.Q)}, gain: {filter.Gain}"); } } @@ -56,7 +53,7 @@ public override void Export(string path) { /// /// All the possible bands that can be selected for YPAO. These are 1/3 octaves apart. /// - static readonly float[] bands = { + static readonly float[] frequencies = { 39.4f, 49.6f, 62.5f, 78.7f, 99.2f, 125.0f, 157.5f, 198.4f, 250, 315, 396.9f, 500, 630, 793.7f, 1000, 1260, 1590, 2000, 2520, 3170, 4000, 5040, 6350, 8000, 10100, 12700, 16000 }; diff --git a/Cavern.QuickEQ.Format/FilterSet/YPAOLiteFilterSet.cs b/Cavern.QuickEQ.Format/FilterSet/YPAOLiteFilterSet.cs new file mode 100644 index 00000000..6fa97c4e --- /dev/null +++ b/Cavern.QuickEQ.Format/FilterSet/YPAOLiteFilterSet.cs @@ -0,0 +1,21 @@ +using Cavern.Channels; + +namespace Cavern.Format.FilterSet { + /// + /// Filter set limited to 4/3 octave band choices for some versions of YPAO. + /// + public class YPAOLiteFilterSet : MultibandPEQFilterSet { + /// + public override double MinGain => -6; + + /// + /// Filter set limited to 4/3 octave band choices for some versions of YPAO. + /// + public YPAOLiteFilterSet(int channels, int sampleRate) : base(channels, sampleRate, 62.5, .75, 7) => LFEBands = 2; + + /// + /// Filter set limited to 4/3 octave band choices for some versions of YPAO. + /// + public YPAOLiteFilterSet(ReferenceChannel[] channels, int sampleRate) : base(channels, sampleRate, 62.5, .75, 7) => LFEBands = 2; + } +} \ No newline at end of file diff --git a/Cavern.QuickEQ/Equalization/PeakingEqualizer.cs b/Cavern.QuickEQ/Equalization/PeakingEqualizer.cs index a80e144f..5b642bdb 100644 --- a/Cavern.QuickEQ/Equalization/PeakingEqualizer.cs +++ b/Cavern.QuickEQ/Equalization/PeakingEqualizer.cs @@ -141,7 +141,7 @@ public PeakingEQ[] GetPeakingEQ(int sampleRate) { /// /// Create a peaking EQ filter set with constant bandwidth between the frequencies. This mimics legacy x-band EQs. /// - public PeakingEQ[] GetPeakingEQ(int sampleRate, double firstBand, int bandsPerOctave, int bands) { + public PeakingEQ[] GetPeakingEQ(int sampleRate, double firstBand, double bandsPerOctave, int bands) { float[] target = source.Visualize(MinFrequency, MaxFrequency, 1024); PeakingEQ[] result = new PeakingEQ[bands]; double bandwidth = 1.0 / bandsPerOctave; diff --git a/Cavern/Remapping/DisassemblerUpmixer.cs b/Cavern/Remapping/DisassemblerUpmixer.cs index d795f7a1..67bff13e 100644 --- a/Cavern/Remapping/DisassemblerUpmixer.cs +++ b/Cavern/Remapping/DisassemblerUpmixer.cs @@ -1,5 +1,6 @@ -using Cavern.Filters; -using System.Numerics; +using System.Numerics; + +using Cavern.Filters; namespace Cavern.Remapping { ///