From 1ab397767a2405e819a0cf408396c6e85c899097 Mon Sep 17 00:00:00 2001 From: Mute Date: Sun, 9 Aug 2026 14:01:19 +0000 Subject: [PATCH] Cleanup pass: remove dead code, fix bugs, simplify Dead code removed: - MusicAnalyzer.BuildWaveFrame (replaced by DrumDetector + BuildMelodyFrame) - MusicAnalyzer.ExtractFeatures simplified to melody-only (removed rhythm band) - MusicAnalyzer.RhythmLow/RhythmHigh constants, TickFeature.RhythmFlux - LiveCapture._liveMaxFlux + _prevRhythmMag (computed, never read) - State.ActualA/ActualB, State.LastSentA/LastSentB (set, never read) - Program.cs StrengthChanged handler (only wrote to dead fields) - Command.Mode property (never referenced) - DrumDetector.FreqKick/Snare/Brass/Silent static arrays (unused) Bugs fixed: - DrumDetector.BuildFrame: freqBytes was byte[16], now byte[4] - CoyoteDevice fallback: use nameFilter param instead of hardcoded string Refactoring: - Server.DoStatus calls BuildStatusPush(null) instead of duplicating - HeatMap: removed redundant colW assignment - Removed unused System.Numerics imports from LiveCapture, MusicAnalyzer --- CoyoteDevice.cs | 2 +- DrumDetector.cs | 7 +---- HeatMap.cs | 3 +-- LiveCapture.cs | 9 +------ MusicAnalyzer.cs | 68 +++--------------------------------------------- Program.cs | 6 ----- Protocol.cs | 4 --- Server.cs | 7 +---- State.cs | 5 ---- 9 files changed, 8 insertions(+), 103 deletions(-) diff --git a/CoyoteDevice.cs b/CoyoteDevice.cs index de01d8e..114ee34 100644 --- a/CoyoteDevice.cs +++ b/CoyoteDevice.cs @@ -33,7 +33,7 @@ public class CoyoteDevice : IDisposable selector = BluetoothLEDevice.GetDeviceSelectorFromPairingState(false); devices = await DeviceInformation.FindAllAsync(selector); var match = devices.FirstOrDefault(d => - d.Name.Contains("47L121000", StringComparison.OrdinalIgnoreCase) || + d.Name.Contains(nameFilter, StringComparison.OrdinalIgnoreCase) || d.Name.Contains("DG-LAB", StringComparison.OrdinalIgnoreCase) || d.Name.Contains("Coyote", StringComparison.OrdinalIgnoreCase)); if (match == null) diff --git a/DrumDetector.cs b/DrumDetector.cs index 0ce4870..b3183a0 100644 --- a/DrumDetector.cs +++ b/DrumDetector.cs @@ -17,11 +17,6 @@ public class DrumDetector readonly bool[] _subSnare = new bool[4]; readonly bool[] _subBrass = new bool[4]; - static readonly byte[] FreqKick = Freq.Compress4(new[] { 150, 150, 150, 150 }); - static readonly byte[] FreqSnare = Freq.Compress4(new[] { 50, 50, 50, 50 }); - static readonly byte[] FreqBrass = Freq.Compress4(new[] { 10, 10, 10, 10 }); - static readonly byte[] FreqSilent = Freq.Compress4(new[] { 10, 10, 10, 10 }); - public void ProcessWindow(double[] magnitude, int sampleRate, int windowSize, int subTickIndex) { if (subTickIndex < 0 || subTickIndex > 3) return; @@ -66,7 +61,7 @@ public class DrumDetector public WaveFrame BuildFrame() { var intensity = new byte[4]; - var freqBytes = new byte[16]; // 4 sub-ticks × 4 bytes (but we use per-sub-tick freq) + var freqBytes = new byte[4]; for (int i = 0; i < 4; i++) { diff --git a/HeatMap.cs b/HeatMap.cs index 6be82e7..1b9555c 100644 --- a/HeatMap.cs +++ b/HeatMap.cs @@ -37,7 +37,6 @@ public class HeatMap : Panel int w = Width; int h = Height; - int colW = Math.Max(1, w / _maxTicks); // Draw axis labels using var font = new Font(FontFamily.GenericMonospace, 7); @@ -48,7 +47,7 @@ public class HeatMap : Panel int plotX = 36; int plotW = w - plotX - 4; int plotH = h - 4; - colW = Math.Max(1, plotW / _maxTicks); + int colW = Math.Max(1, plotW / _maxTicks); for (int i = 0; i < _history.Count; i++) { diff --git a/LiveCapture.cs b/LiveCapture.cs index c64f5fb..d1b7a79 100644 --- a/LiveCapture.cs +++ b/LiveCapture.cs @@ -1,4 +1,3 @@ -using System.Numerics; using FftSharp; using NAudio.CoreAudioApi; using NAudio.Wave; @@ -16,8 +15,6 @@ public class LiveCapture : IDisposable readonly Queue _sampleBuffer = new(); readonly object _bufferLock = new(); - double[]? _prevRhythmMag; - double _liveMaxFlux; double _liveMaxMelodyEnergy; int _sampleRate; int _fftsPerTick; @@ -131,13 +128,9 @@ public class LiveCapture : IDisposable var spectrum = FFT.Forward(windowData); var mag = FFT.Magnitude(spectrum); - var (rhythmEnergy, rhythmFlux, melodyEnergy, melodyFreq) = - MusicAnalyzer.ExtractFeatures(mag, _prevRhythmMag, _sampleRate); - - _prevRhythmMag = mag; + var (melodyEnergy, melodyFreq) = MusicAnalyzer.ExtractFeatures(mag, _sampleRate); // Adaptive normalization: running max with slow decay - _liveMaxFlux = Math.Max(rhythmFlux, _liveMaxFlux * 0.999); _liveMaxMelodyEnergy = Math.Max(melodyEnergy, _liveMaxMelodyEnergy * 0.999); // Drum detection: map this FFT window to a sub-tick (0-3) diff --git a/MusicAnalyzer.cs b/MusicAnalyzer.cs index 586811e..3b3f654 100644 --- a/MusicAnalyzer.cs +++ b/MusicAnalyzer.cs @@ -1,4 +1,3 @@ -using System.Numerics; using FftSharp; namespace Substation; @@ -9,35 +8,15 @@ public static class MusicAnalyzer public const int HopSize = 1024; public const double TickDuration = 0.1; - const double RhythmLow = 20, RhythmHigh = 250; const double MelodyLow = 300, MelodyHigh = 4000; - public static (double rhythmEnergy, double rhythmFlux, double melodyEnergy, double melodyFreq) - ExtractFeatures(double[] magnitude, double[]? prevRhythmMag, int sampleRate) + public static (double melodyEnergy, double melodyFreq) + ExtractFeatures(double[] magnitude, int sampleRate) { double binWidth = (double)sampleRate / WindowSize; - int rhythmLoBin = (int)(RhythmLow / binWidth); - int rhythmHiBin = (int)(RhythmHigh / binWidth); int melodyLoBin = (int)(MelodyLow / binWidth); int melodyHiBin = (int)(MelodyHigh / binWidth); - // Rhythm band energy - double rhythmEnergy = 0; - for (int i = rhythmLoBin; i <= rhythmHiBin && i < magnitude.Length; i++) - rhythmEnergy += magnitude[i] * magnitude[i]; - rhythmEnergy = Math.Sqrt(rhythmEnergy / (rhythmHiBin - rhythmLoBin + 1)); - - // Spectral flux (positive change in rhythm band) - double rhythmFlux = 0; - if (prevRhythmMag != null) - { - for (int i = rhythmLoBin; i <= rhythmHiBin && i < magnitude.Length; i++) - { - double diff = magnitude[i] - prevRhythmMag[i]; - if (diff > 0) rhythmFlux += diff; - } - } - // Melody band: energy + dominant frequency (spectral peak) double melodyEnergy = 0; double peakMag = 0; @@ -55,7 +34,7 @@ public static class MusicAnalyzer melodyEnergy = Math.Sqrt(melodyEnergy / (melodyHiBin - melodyLoBin + 1)); double melodyFreq = peakBin * binWidth; - return (rhythmEnergy, rhythmFlux, melodyEnergy, melodyFreq); + return (melodyEnergy, melodyFreq); } public static int MapPitchToPeriod(double hz) @@ -73,7 +52,6 @@ public static class MusicAnalyzer public class TickFeature { - public double RhythmFlux; public double MelodyEnergy; public double MelodyCount; public readonly List MelodyFreqSamples = new(); @@ -105,44 +83,4 @@ public static class MusicAnalyzer return new WaveFrame(freqB, intB); } - - public static (WaveFrame chA, WaveFrame chB) BuildWaveFrame(TickFeature tf, double maxFlux, double maxMelodyEnergy) - { - const int rhythmFreqMs = 150; - - double normalizedFlux = maxFlux > 0 ? tf.RhythmFlux / maxFlux : 0; - int onsetIntensity = (int)Math.Round(normalizedFlux * 100); - var intA = new[] - { - (byte)Math.Clamp(onsetIntensity, 0, 100), - (byte)Math.Clamp(onsetIntensity * 6 / 10, 0, 100), - (byte)Math.Clamp(onsetIntensity * 3 / 10, 0, 100), - (byte)0 - }; - var freqA = Freq.Compress4(new[] { rhythmFreqMs, rhythmFreqMs, rhythmFreqMs, rhythmFreqMs }); - - double avgEnergy = tf.MelodyCount > 0 ? tf.MelodyEnergy / tf.MelodyCount : 0; - double normalizedEnergy = maxMelodyEnergy > 0 ? avgEnergy / maxMelodyEnergy : 0; - int melodyIntensity = (int)Math.Round(normalizedEnergy * 80); - melodyIntensity = Math.Clamp(melodyIntensity, 0, 100); - - double weightedFreq = 0; - double totalWeight = 0; - foreach (var f in tf.MelodyFreqSamples) - { - weightedFreq += f * f; - totalWeight += f; - } - double avgMelodyHz = totalWeight > 0 ? weightedFreq / totalWeight : 500; - int estimsMs = MapPitchToPeriod(avgMelodyHz); - - var intB = new[] - { - (byte)melodyIntensity, (byte)melodyIntensity, - (byte)melodyIntensity, (byte)melodyIntensity - }; - var freqB = Freq.Compress4(new[] { estimsMs, estimsMs, estimsMs, estimsMs }); - - return (new WaveFrame(freqA, intA), new WaveFrame(freqB, intB)); - } } diff --git a/Program.cs b/Program.cs index 1d1995b..e8ac561 100644 --- a/Program.cs +++ b/Program.cs @@ -13,12 +13,6 @@ static class Program var state = new State(); var server = new Server(device, state, Port); - device.StrengthChanged += (a, b) => - { - state.ActualA = a; - state.ActualB = b; - }; - Application.Run(new MainForm(device, state, server)); } } diff --git a/Protocol.cs b/Protocol.cs index da2b94f..05f06c2 100644 --- a/Protocol.cs +++ b/Protocol.cs @@ -105,10 +105,6 @@ public class Command [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string? Channel { get; set; } - [JsonPropertyName("mode")] - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string? Mode { get; set; } - [JsonPropertyName("value")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public int? Value { get; set; } diff --git a/Server.cs b/Server.cs index ffdfda9..19bb0b6 100644 --- a/Server.cs +++ b/Server.cs @@ -242,12 +242,7 @@ public class Server string DoStatus() { - return JsonSerializer.Serialize(new StatusResponse - { - Connected = _device.IsConnected, - StrengthA = _device.StrengthA, - StrengthB = _device.StrengthB - }, JsonOpts); + return BuildStatusPush(null); } string DoStrength(Command cmd) diff --git a/State.cs b/State.cs index 2eb0199..257776f 100644 --- a/State.cs +++ b/State.cs @@ -15,8 +15,6 @@ public class State public readonly ConcurrentQueue StreamA = new(); public readonly ConcurrentQueue StreamB = new(); - public int ActualA, ActualB; - public int LastSentA, LastSentB; public double LimitScaleA, LimitScaleB; public byte[]? LastFreqA, LastIntA, LastFreqB, LastIntB; public bool LastActiveA, LastActiveB; @@ -133,8 +131,6 @@ public class State : (byte)Math.Clamp(desired, 0, max); var valA = ApplyLimit(DesiredA, MaxA, LimitModeA); var valB = ApplyLimit(DesiredB, MaxB, LimitModeB); - LastSentA = valA; - LastSentB = valB; LimitScaleA = DesiredA > 0 ? (double)valA / DesiredA : 0; LimitScaleB = DesiredB > 0 ? (double)valB / DesiredB : 0; DirtyA = false; @@ -167,7 +163,6 @@ public class State (modeA, modeB) = (modeB, modeA); (freqA, freqB) = (freqB, freqA); (intA, intB) = (intB, intA); - (LastSentA, LastSentB) = (LastSentB, LastSentA); (LastFreqA, LastFreqB) = (LastFreqB, LastFreqA); (LastIntA, LastIntB) = (LastIntB, LastIntA); (LastActiveA, LastActiveB) = (LastActiveB, LastActiveA);