Skip to content

Commit

Permalink
Basic filter additions to graph
Browse files Browse the repository at this point in the history
  • Loading branch information
VoidXH committed Apr 29, 2024
1 parent 4079de4 commit 401278c
Show file tree
Hide file tree
Showing 33 changed files with 624 additions and 328 deletions.
6 changes: 4 additions & 2 deletions Cavern.QuickEQ.Format/ConfigurationFile/ConfigurationFile.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;

using Cavern.Channels;
using Cavern.Filters;
using Cavern.Filters.Utilities;

namespace Cavern.Format.ConfigurationFile {
Expand All @@ -17,10 +19,10 @@ public abstract class ConfigurationFile {
/// <summary>
/// Create an empty configuration file with the passed input channel names/labels.
/// </summary>
public ConfigurationFile(string[] inputs) {
protected ConfigurationFile(string[] inputs) {
InputChannels = new (string name, FilterGraphNode root)[inputs.Length];
for (int i = 0; i < inputs.Length; i++) {
InputChannels[i] = (inputs[i], new FilterGraphNode(null));
InputChannels[i] = (inputs[i], new FilterGraphNode(new InputChannel(inputs[i])));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public EqualizerAPOConfigurationFile(string path, int sampleRate) : base(channel
AddConfigFile(path, lastNodes, activeChannels, sampleRate);

for (int i = 0; i < channelLabels.Length; i++) { // Output markers
lastNodes[channelLabels[i]].AddChild(new FilterGraphNode(new BypassFilter(channelLabels[i] + '\'')));
lastNodes[channelLabels[i]].AddChild(new FilterGraphNode(new OutputChannel(channelLabels[i])));
}
Optimize();
}
Expand Down
30 changes: 30 additions & 0 deletions Cavern.QuickEQ.Format/Filters/InputChannel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Cavern.Channels;
using Cavern.Format.ConfigurationFile;

namespace Cavern.Filters {
/// <summary>
/// Marks an input channel on a parsed <see cref="ConfigurationFile"/> graph.
/// </summary>
/// <remarks>This filter is part of the Cavern.QuickEQ.Format library and is not available in the Cavern library's Filters namespace,
/// because it shall only be created by <see cref="ConfigurationFile"/>s.</remarks>
public class InputChannel : BypassFilter {
/// <summary>
/// The channel for which this filter marks the beginning of the filter pipeline.
/// </summary>
public ReferenceChannel Channel { get; }

/// <summary>
/// Marks an input channel on a parsed <see cref="ConfigurationFile"/> graph.
/// </summary>
/// <param name="channel">The channel for which this filter marks the beginning of the filter pipeline</param>
protected internal InputChannel(ReferenceChannel channel) : base(channel.GetShortName() + " input") => Channel = channel;

/// <summary>
/// Marks an input channel on a parsed <see cref="ConfigurationFile"/> graph.
/// </summary>
/// <param name="channel">The channel for which this filter marks the beginning of the filter pipeline</param>
protected internal InputChannel(string channel) :
base(ReferenceChannelExtensions.FromStandardName(channel).GetShortName() + " input") =>
Channel = ReferenceChannelExtensions.FromStandardName(channel);
}
}
30 changes: 30 additions & 0 deletions Cavern.QuickEQ.Format/Filters/OutputChannel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Cavern.Channels;
using Cavern.Format.ConfigurationFile;

namespace Cavern.Filters {
/// <summary>
/// Marks an output channel on a parsed <see cref="ConfigurationFile"/> graph.
/// </summary>
/// <remarks>This filter is part of the Cavern.QuickEQ.Format library and is not available in the Cavern library's Filters namespace,
/// because it shall only be created by <see cref="ConfigurationFile"/>s.</remarks>
public class OutputChannel : BypassFilter {
/// <summary>
/// The channel for which this filter marks the end of the filter pipeline.
/// </summary>
public ReferenceChannel Channel { get; }

/// <summary>
/// Marks an output channel on a parsed <see cref="ConfigurationFile"/> graph.
/// </summary>
/// <param name="channel">The channel for which this filter marks the end of the filter pipeline</param>
protected internal OutputChannel(ReferenceChannel channel) : base(channel.GetShortName() + " output") => Channel = channel;

/// <summary>
/// Marks an output channel on a parsed <see cref="ConfigurationFile"/> graph.
/// </summary>
/// <param name="channel">The channel for which this filter marks the end of the filter pipeline</param>
protected internal OutputChannel(string channel) :
base(ReferenceChannelExtensions.FromStandardName(channel).GetShortName() + " output") =>
Channel = ReferenceChannelExtensions.FromStandardName(channel);
}
}
2 changes: 1 addition & 1 deletion Cavern/Channels/ChannelPrototype.Consts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public static readonly ChannelPrototype
/// <summary>
/// Semi-standard (Equalizer APO) channel names.
/// </summary>
const string frontLeftMark = "L",
internal const string frontLeftMark = "L",
frontRightMark = "R",
frontCenterMark = "C",
screenLFEMark = "LFE",
Expand Down
8 changes: 4 additions & 4 deletions Cavern/Channels/ChannelPrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public static ChannelPrototype Get(int channel, int channels) {
/// </summary>
public static ChannelPrototype[] Get(ReferenceChannel[] source) {
ChannelPrototype[] result = new ChannelPrototype[source.Length];
for (int i = 0; i < source.Length; ++i) {
for (int i = 0; i < source.Length; i++) {
result[i] = Mapping[(int)source[i]];
}
return result;
Expand All @@ -129,7 +129,7 @@ public static ChannelPrototype[] Get(ReferenceChannel[] source) {
/// </summary>
public static ChannelPrototype[] GetAlternative(ReferenceChannel[] source) {
ChannelPrototype[] result = new ChannelPrototype[source.Length];
for (int i = 0; i < source.Length; ++i) {
for (int i = 0; i < source.Length; i++) {
int index = (int)source[i];
ChannelPrototype old = Mapping[index];
Channel moved = new Channel(AlternativePositions[index], old.LFE);
Expand All @@ -147,7 +147,7 @@ public static ChannelPrototype[] GetAlternative(ReferenceChannel[] source) {
/// </summary>
public static string[] GetNames(ReferenceChannel[] source) {
string[] result = new string[source.Length];
for (int i = 0; i < source.Length; ++i) {
for (int i = 0; i < source.Length; i++) {
result[i] = Mapping[(int)source[i]].Name;
}
return result;
Expand Down Expand Up @@ -239,7 +239,7 @@ static ReferenceChannel[] GetStandardMatrix(ReferenceChannel[][] database, int c
ReferenceChannel[] matrix = database[subcount];
if (subcount != count) {
Array.Resize(ref matrix, count);
for (int i = subcount; i < count; ++i) {
for (int i = subcount; i < count; i++) {
matrix[i] = ReferenceChannel.Unknown;
}
}
Expand Down
27 changes: 27 additions & 0 deletions Cavern/Channels/ReferenceChannelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,32 @@ public static bool IsHeight(this ReferenceChannel channel) =>
(channel >= ReferenceChannel.TopFrontLeft && channel <= ReferenceChannel.TopSideRight) ||
channel == ReferenceChannel.TopFrontCenter || channel == ReferenceChannel.GodsVoice ||
(channel >= ReferenceChannel.TopRearLeft && channel <= ReferenceChannel.TopRearCenter);

/// <summary>
/// Converts a standard channel shorthand to a <see cref="ReferenceChannel"/>.
/// </summary>
public static ReferenceChannel FromStandardName(string name) {
switch (name) {
case ChannelPrototype.frontLeftMark:
return ReferenceChannel.FrontLeft;
case ChannelPrototype.frontRightMark:
return ReferenceChannel.FrontRight;
case ChannelPrototype.frontCenterMark:
return ReferenceChannel.FrontCenter;
case ChannelPrototype.screenLFEMark:
case ChannelPrototype.subwooferMark:
return ReferenceChannel.ScreenLFE;
case ChannelPrototype.rearLeftMark:
return ReferenceChannel.RearLeft;
case ChannelPrototype.rearRightMark:
return ReferenceChannel.RearRight;
case ChannelPrototype.sideLeftMark:
return ReferenceChannel.SideLeft;
case ChannelPrototype.sideRightMark:
return ReferenceChannel.SideRight;
default:
return ReferenceChannel.Unknown;
}
}
}
}
3 changes: 3 additions & 0 deletions Cavern/Filters/Allpass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ namespace Cavern.Filters {
/// Simple first-order allpass filter.
/// </summary>
public class Allpass : PhaseSwappableBiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.Allpass;

/// <summary>
/// Simple first-order allpass filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Cavern/Filters/Bandpass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace Cavern.Filters {
/// Simple first-order bandpass filter.
/// </summary>
public class Bandpass : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.Bandpass;

/// <summary>
/// Simple first-order bandpass filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
7 changes: 6 additions & 1 deletion Cavern/Filters/BiquadFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public double Gain {
public float b2 { get; protected set; }
#pragma warning restore IDE1006 // Naming Styles

/// <summary>
/// The enumerated type of this filter.
/// </summary>
public abstract BiquadFilterType FilterType { get; }

/// <summary>
/// Center frequency (-3 dB point) of the filter.
/// </summary>
Expand Down Expand Up @@ -225,6 +230,6 @@ protected void SetupPass(float cosW0, float alpha, float divisor, float b1Pre) {
/// <summary>
/// Display the filter's parameters when converting to string.
/// </summary>
public override string ToString() => $"Biquad filter at {centerFreq} Hz, Q: {q}, gain: {gain} dB";
public override string ToString() => $"{FilterType} at {centerFreq} Hz, Q: {q}, gain: {gain} dB";
}
}
3 changes: 3 additions & 0 deletions Cavern/Filters/HighShelf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace Cavern.Filters {
/// Simple first-order high shelf filter.
/// </summary>
public class HighShelf : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.HighShelf;

/// <summary>
/// Simple first-order high shelf filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Cavern/Filters/Highpass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace Cavern.Filters {
/// Simple first-order highpass filter.
/// </summary>
public class Highpass : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.Highpass;

/// <summary>
/// Simple first-order highpass filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Cavern/Filters/LowShelf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace Cavern.Filters {
/// Simple first-order low shelf filter.
/// </summary>
public class LowShelf : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.LowShelf;

/// <summary>
/// Simple first-order low shelf filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Cavern/Filters/Lowpass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace Cavern.Filters {
/// Simple first-order lowpass filter.
/// </summary>
public class Lowpass : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.Lowpass;

/// <summary>
/// Simple first-order lowpass filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Cavern/Filters/Notch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ namespace Cavern.Filters {
/// Simple first-order notch filter.
/// </summary>
public class Notch : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.Notch;

/// <summary>
/// Simple first-order notch filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions Cavern/Filters/PeakingEQ.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ namespace Cavern.Filters {
/// Simple first-order peaking filter.
/// </summary>
public class PeakingEQ : BiquadFilter {
/// <inheritdoc/>
public override BiquadFilterType FilterType => BiquadFilterType.PeakingEQ;

/// <summary>
/// Simple first-order peaking filter with maximum flatness and no additional gain.
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions Cavern/Filters/Utilities/FilterGraphNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ public class FilterGraphNode {
/// <param name="filter">The wrapped filter</param>
public FilterGraphNode(Filter filter) => Filter = filter;

/// <summary>
/// Place a <see cref="FilterGraphNode"/> between this and the <see cref="children"/>.
/// </summary>
public void AddBeforeChildren(FilterGraphNode newChild) {
newChild.children.AddRange(children);
for (int i = 0, c = children.Count; i < c; i++) {
children[i].parents.Clear();
children[i].parents.Add(newChild);
}
children.Clear();
AddChild(newChild);
}

/// <summary>
/// Place a <paramref name="filter"/> between this and the <see cref="children"/> and return the new node containing that filter.
/// </summary>
public FilterGraphNode AddBeforeChildren(Filter filter) {
FilterGraphNode node = new FilterGraphNode(filter);
AddBeforeChildren(node);
return node;
}

/// <summary>
/// Append a node to process this filter's result in the filter graph.
/// </summary>
Expand Down
12 changes: 10 additions & 2 deletions CavernSamples/Cavern.WPF/BiquadEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
xmlns:local="clr-namespace:Cavern.WPF"
x:Class="Cavern.WPF.BiquadEditor"
mc:Ignorable="d"
Title="Biquad Editor" Width="536" Height="370">
Title="Biquad Editor" Width="536" Height="372">
<Grid>
<Image x:Name="image" Margin="10,10,0,0" Height="200" HorizontalAlignment="Left" VerticalAlignment="Top" Width="500"/>
<TextBlock Margin="10,218,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="Filter type:"/>
<ComboBox x:Name="filterTypes" Margin="130,215,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" SelectionChanged="FilterTypeChanged"/>
<ComboBox x:Name="filterTypes" Margin="130,215,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"
SelectionChanged="FilterTypeChanged"/>
<TextBlock Margin="10,243,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="Center frequency:"/>
<TextBox x:Name="centerFreq" Margin="130,242,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Text="632.456"
TextChanged="NumericFilterDataChanged"/>
Expand All @@ -22,5 +23,12 @@
TextChanged="NumericFilterDataChanged"/>
<CheckBox x:Name="swapPhase" Margin="10,311,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Swap phase"
Checked="PhaseSwapChanged" Unchecked="PhaseSwapChanged"/>
<CheckBox x:Name="spectrumColorDisplay" Margin="0,215,10,0" HorizontalAlignment="Right" VerticalAlignment="Top" Width="100"
Content="Spectrum" Checked="DisableCheck"/>
<CheckBox x:Name="phaseColorDisplay" Margin="0,235,10,0" HorizontalAlignment="Right" VerticalAlignment="Top" Width="100"
Content="Phase" Checked="DisableCheck"/>
<Button Margin="0,0,95,10" Width="80" Height="20" HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="OK" Click="OK"/>
<Button Margin="0,0,10,10" Width="80" Height="20" HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="Cancel"
Click="Cancel"/>
</Grid>
</Window>
Loading

0 comments on commit 401278c

Please sign in to comment.