diff --git a/LibSidWiz/Channel.cs b/LibSidWiz/Channel.cs index 2ea033d..54d463a 100644 --- a/LibSidWiz/Channel.cs +++ b/LibSidWiz/Channel.cs @@ -47,6 +47,7 @@ public class Channel: IDisposable private bool _clip; private Sides _side = Sides.Mix; private bool _smoothLines = true; + private bool _filter = false; public enum Sides { @@ -79,7 +80,7 @@ public enum Sides IsEmpty = false; Console.WriteLine($"- Reading {Filename}"); - _samples = new SampleBuffer(Filename, Side); + _samples = new SampleBuffer(Filename, Side, HighPassFilter); SampleRate = _samples.SampleRate; Length = _samples.Length; @@ -171,6 +172,20 @@ public Sides Side { _side = value; Changed?.Invoke(this, true); + LoadDataAsync(); + } + } + + [Category("Data")] + [Description("If enabled, high pass filtering will be used to remove DC offsets")] + public bool HighPassFilter + { + get => _filter; + set + { + _filter = value; + Changed?.Invoke(this, true); + LoadDataAsync(); } } diff --git a/LibSidWiz/SampleBuffer.cs b/LibSidWiz/SampleBuffer.cs index d390634..e7c6687 100644 --- a/LibSidWiz/SampleBuffer.cs +++ b/LibSidWiz/SampleBuffer.cs @@ -1,4 +1,5 @@ using System; +using NAudio.Dsp; using NAudio.Wave; namespace LibSidWiz @@ -34,7 +35,7 @@ public bool Contains(long index) public float Min { get; private set; } - public SampleBuffer(string filename, Channel.Sides side) + public SampleBuffer(string filename, Channel.Sides side, bool filter) { _reader = new WaveFileReader(filename); Count = (int) _reader.SampleCount; @@ -53,18 +54,21 @@ public SampleBuffer(string filename, Channel.Sides side) break; } + if (filter) + { + _sampleProvider = new HighPassSampleProvider(_sampleProvider); + } + _chunk1 = new Chunk { Buffer = new float[ChunkSize], - Offset = 0 + Offset = -1 }; - _sampleProvider.Read(_chunk1.Buffer, 0, ChunkSize); _chunk2 = new Chunk { Buffer = new float[ChunkSize], - Offset = ChunkSize + Offset = -1 }; - _sampleProvider.Read(_chunk2.Buffer, 0, ChunkSize); } public void Dispose() @@ -120,4 +124,31 @@ public void Analyze() } } } + + internal class HighPassSampleProvider : ISampleProvider + { + private readonly ISampleProvider _sampleProvider; + private BiQuadFilter _filter; + + public HighPassSampleProvider(ISampleProvider sampleProvider) + { + _sampleProvider = sampleProvider; + _filter = BiQuadFilter.HighPassFilter(sampleProvider.WaveFormat.SampleRate, 20, 1); + } + + public int Read(float[] buffer, int offset, int count) + { + int result = _sampleProvider.Read(buffer, offset, count); + + // Apply the filter + for (int i = 0; i < result; ++i) + { + buffer[i] = _filter.Transform(buffer[i]); + } + + return result; + } + + public WaveFormat WaveFormat => _sampleProvider.WaveFormat; + } } diff --git a/SidWizPlus/Program.cs b/SidWizPlus/Program.cs index 0de9596..273f2c3 100644 --- a/SidWizPlus/Program.cs +++ b/SidWizPlus/Program.cs @@ -99,10 +99,15 @@ private class Settings // ReSharper disable once StringLiteralTypo [Option('t', "triggeralgorithm", Required = false, HelpText = "Trigger algorithm name", DefaultValue = nameof(PeakSpeedTrigger))] public string TriggerAlgorithm { get; set; } + // ReSharper disable once StringLiteralTypo [Option("triggerlookahead", Required = false, HelpText = "Number of frames to allow the trigger to look ahead, zero means no lookahead", DefaultValue = 0)] public int TriggerLookahead { get; set; } + // ReSharper disable once StringLiteralTypo + [Option("highpass", Required = false, HelpText = "Enable high-pass filtering", DefaultValue = false)] + public bool HighPass { get; set; } + // ReSharper disable once StringLiteralTypo [Option('p', "previewframeskip", Required = false, HelpText = "Enable a preview window with the specified frameskip - higher values give faster rendering by not drawing every frame to the screen.")] public int PreviewFrameskip { get; set; } @@ -304,7 +309,8 @@ static void Main(string[] args) LabelFont = settings.ChannelLabelsFont == null ? null : new Font(settings.ChannelLabelsFont, settings.ChannelLabelsSize), - LabelColor = ParseColor(settings.ChannelLabelsColor) + LabelColor = ParseColor(settings.ChannelLabelsColor), + HighPassFilter = settings.HighPass }; channel.LoadDataAsync().Wait(); channel.ViewWidthInMilliseconds = settings.ViewWidthMs; @@ -590,7 +596,7 @@ private static void Render(Settings settings, IReadOnlyCollection chann } } - if (settings.LogoImageFile != null) + if (!string.IsNullOrEmpty(settings.LogoImageFile)) { using (var bm = Image.FromFile(settings.LogoImageFile)) {