Commit Graph

22 Commits

Author SHA1 Message Date
mute 1ce20544a4 Add live capture diagnostic logging to live.log
- Logs device name, audio format (bit depth, channels, sample rate)
- Logs dataAvailable callbacks (every 100th): bytes, samples, buffer size
- Logs FFT ticks (every 50th): melody energy, freq, intensity A/B
- Warning if data arrives but buffer doesn't fill
- Logs totals + any exception on stop
- Writes to live.log next to .exe, cleared on each start
2026-08-14 09:54:47 +00:00
mute 496cc5a6b2 Support all 5 xToys pattern types
- script-v3: reworked with initialActions channel mapping, freq detection
  by name, single-channel duplication, full expression evaluator (pow, arithmetic)
- basic-v2: handle frequencyControl:true, 3-channel (ch3 ignored)
- funscript/draw: resample {at,pos} timeline to 100ms ticks via linear interpolation
- audio: resample flat float array to 100ms ticks using length in seconds
- EvaluateExpression replaces ResolveExpr: DataTable.Compute + pow() pre-processing
- All types: single-channel patterns duplicate to both A/B
- All types: missing frequency data uses fixed 150ms default
2026-08-14 09:49:58 +00:00
mute 1ab397767a 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
2026-08-09 14:01:19 +00:00
mute badc599dee Bump version to 0.3.0 2026-08-09 12:04:30 +00:00
mute 5efdd63212 Remove Test button, move Stop All to right edge
- Removed Test button, OnTest, RunTestAsync, IsTestRunning
- Remaining buttons (Live, Pattern, Random, Stop All) at 80px each
- Stop All moved to right edge (x=324)
2026-08-09 12:04:08 +00:00
mute f1e7d976ca Add Random button (pink noise generator) with counterphase channels
- Voss-McCartney pink noise (1/f spectrum) for intensity and frequency
- Separate state per channel, channel B inverted for counterphase
- Intensity capped at 80 for comfort, frequency spans full 10-1000ms range
- Runs continuously, stopped via Stop All or switching modes
- 5th button (68px), all buttons resized to fit one row
2026-08-09 12:01:51 +00:00
mute 4e36580b22 Fix heat map scaling, add per-channel amplifier
- Add per-channel amplifier (0-100, 1.0x to 10.0x) applied to intensity
  before limiter gates strength
- Fix heat map scaling: use LimitScaleA/B (valA/DesiredA ratio) instead
  of valA/200 — was capping colors at green, never reaching orange
- Scale heat map intensity by limiter ratio so colors reflect actual
  output after limiter
- Remove dead LastIntensityA/B field (replaced by heat map scaling)
- Amp trackbars: 0=1.0x, 100=10.0x, integer value labels
- Close button quits app instead of hiding to tray
2026-08-09 11:55:16 +00:00
mute 4ad85f57ec Close button quits app instead of hiding to tray
- OnFormClosing no longer intercepts close button — app quits on X
- Minimize still hides to tray (OnResize unchanged)
- Removed unused _closingFromTray flag
- Tray Exit and tray double-click restore unchanged
2026-08-09 11:33:36 +00:00
mute 4c44d48a02 Add drum detection for channel A in live capture
- DrumDetector.cs: 3-band onset detection (kick/snare/brass) with adaptive
  thresholds, per-sub-tick timing within 100ms frames
- Kick: low-band onset, 150ms deep thump
- Snare: broadband (mid+high) onset, 50ms mid punch
- Brass: high-only onset, 10ms buzzy
- Priority: kick > snare > brass when multiple hit same sub-tick
- Intensity = max (100) on hit, 0 on silence — user limiter scales down
- MusicAnalyzer: add BuildMelodyFrame for chB only (pitch+energy)
- LiveCapture: chA now from DrumDetector, chB unchanged (melody)
- Sub-tick mapping: FFT window position → 0-3 within each 100ms tick
2026-08-09 11:32:16 +00:00
mute abb5364bb4 Bump version to 0.2.0 2026-08-08 19:55:19 +00:00
mute e43b1f30cd Remove music button and MP3 decode, keep live capture only
- Remove Music button, OnMusic/RunMusicAsync/StopMusic and all music fields
- MusicAnalyzer: remove Analyze, DecodeToMono, MusicPattern record;
  keep ExtractFeatures/MapPitchToPeriod/BuildWaveFrame/TickFeature (used by LiveCapture)
- Remove unused NAudio.Wave and System.Diagnostics imports from MainForm
- Fix LiveCapture overlap: sliding window with 50% overlap (was dropping every other frame)
- Buttons resized to 80px (Test/Live/Pattern/Stop All)
2026-08-08 19:52:56 +00:00
mute bbd9bb6d6b Add xToys pattern import via URL paste
- XToysPattern.cs: fetch pattern from xtoys.app API (one call), parse
  script-v3 JSON, resolve slider defaults, evaluate sine/straight steps
  to WaveFrames at 100ms resolution
- Frequency mapping: 0%=1000ms deep, 100%=10ms buzzy
- MainForm: Pattern button + input dialog, continuously enqueues pattern
  frames as a loop, Stop All cancels
- Fix: handle JSON values that are numbers vs strings (end/start fields)
- NOTES.md: xToys slider parameter intel + frequency mapping docs
2026-08-08 19:44:25 +00:00
mute ccc5093ee2 Add live audio capture via WASAPI loopback
- LiveCapture.cs: real-time WASAPI loopback capture with rolling buffer
  and continuous FFT analysis, enqueues WaveFrames at ~10Hz
- MusicAnalyzer.cs: refactored ExtractFeatures/MapPitchToPeriod/BuildWaveFrame
  as public reusable methods with sampleRate parameter
- MainForm: audio device selector (defaults to system default), Live button
  starts/stops capture, Stop All stops live too
- Adaptive normalization (running max with slow decay) for live volume changes
2026-08-08 19:20:46 +00:00
mute 933c7ede38 Move Swap to connect row, show limiter values, fix trackbar keys
- Swap checkbox moved up to the Connect/device line
- Limiter values shown as separate labels (plain, 32px wide for 3 digits)
- Trackbar keyboard: Up/PageUp/Home = increase, Down/PageDown/End = decrease
- Fix Lim B trackbar clipping (moved down to avoid overlap with Lim A)
2026-08-08 11:58:37 +00:00
mute 8b51ff19a8 Make UI event-driven, heat maps at 10Hz from tick loop
- Heat maps fed from tick loop via BeginInvoke (10Hz, one column per tick)
- BLE label updates on ConnectionChanged event (was 4Hz poll)
- Recv gauges update on StrengthChanged event (B1 notifications)
- Button states refreshed via RefreshButtonStates on all state changes
- Status timer reduced from 250ms to 1s — only music label + tray icon
- Eliminates 4Hz choppy polling
2026-08-08 11:38:05 +00:00
mute 33e289d596 Add per-channel independent limit controls
- Separate Lim A / Lim B trackbars (0-200, default 30 each)
- Separate Scale A / Scale B checkboxes (clamp vs scale per channel)
- State.SetLimitA/SetLimitB with independent LimitModeA/LimitModeB
- ConsumeTick applies per-channel limit and mode
2026-08-08 11:26:44 +00:00
mute 325022d27c Fix Send gauges showing intensity, zero when idle
- Send gauges now show waveform intensity (0-100) not strength ceiling
- State.LastIntensityA/B tracks average intensity per tick
- Zero when no pattern/stream active (was 25 due to IntensityOff 101 sentinel)
- Recv gauges unchanged (device-reported strength 0-200)
2026-08-08 11:18:01 +00:00
mute 84eba7d094 Bump version to 0.1.6, surface in form title 2026-08-08 11:07:15 +00:00
mute 612385af7f Add Send/Recv gauges, fix tick loop to consume without BLE
- Four gauges: Send A/B (commanded) and Recv A/B (device-reported)
- State.LastSentA/B tracks what would be sent after limiting
- ConsumeTick always runs; only SendB0 gated on IsConnected
- Stream queues drain correctly in dev mode (no box)
- Tray icon hot state works without BLE connected
- Removed strength text label, widened form to 420x360
2026-08-08 11:03:44 +00:00
mute 4ae5c397fd Fix crash on startup: call OnLimitChanged after _chkScale is initialized
The manual OnLimitChanged(null, EventArgs.Empty) call in the constructor
was placed before _chkScale was created, causing a NullReferenceException
because the handler reads _chkScale.Checked. Moved the call to after both
_limitBar and _chkScale are created and wired.
2026-08-08 10:55:30 +00:00
mute 44421a51e3 Implement Substation: BLE-WS bridge with music-reactive e-stim
- Renamed from CoyoteBridge to Substation (namespace, classes, UI)
- BLE connection via WinRT with graceful disconnect handling
- WebSocket server (127.0.0.1:8765) with single-client, push events
  for BLE connect/disconnect transitions
- Operator strength limiter (clamp/scale modes, default 30)
- Tray icon with 3 states: neutral/active/hot (runtime-drawn voltage glyph)
- A/B strength gauges, hide-on-minimise to tray
- Music mode: MP3 decode + FFT analysis (NAudio + FftSharp), rhythm→ch A,
  melody→ch B, pre-analyzed with synced audio playback
- Test/Stop All work without BLE connected (dev mode)
- WS device-driving commands error when BLE not connected; ping/status/
  connect always work
- TreatWarningsAsErrors, LangVersion=latest
- .gitignore, README with full API docs + attribution
2026-08-08 10:46:25 +00:00
mute 2bbdcfd9fe Initial commit 2026-08-08 10:44:35 +00:00