What's New
Server-side RDS Decoding
- RDS decoder fully wired into the Opus pipeline (was silently emitting
nullsince day 1) - Complete rewrite of the Go RDS decoder to match the IEC 62106 standard — same algorithm as the working TypeScript client-side decoder
- PTY name lookup table, proper biphase clock recovery, differential Manchester decoding, correct CRC syndrome calculation
- PS, RT, PI, PTY fields streamed to client as JSON on group completion (~11 Hz max update rate)
Wire-Driven Audio Protocol
- Every frame is now self-describing — client is a dumb terminal
MSG_IQ(0x02): 6-byte header with sample rate, channels, reservedMSG_IQ_ADPCM(0x09): 10-byte header with sample count, sample rate, channels, reservedMSG_AUDIO_OPUS(0x0C): unchanged (was already self-describing)- Client demodulator sample rate driven entirely from wire headers — no proactive resets needed
Opus Chipmunk Fix
- Root cause:
UpdateSampleRate(240000)was called beforeSetMode('wfm')on mode switch, sodecimFactor = 240000/48000 = 5. FmStereoDemod already decimates 240k→48k internally, so the pipeline applied 5× decimation again → audio at 5× speed (chipmunk). Fixed:SetMode()now recalculatesdecimFactorwith the correct new mode. - Opus decoder lifecycle is now owned exclusively by
MSG_AUDIO_OPUShandler —setMode(),tune(),setIqCodec()no longer touch the decoder opusDecoderChannelsupdated eagerly to prevent double-init races
Admin FFT Hot-Apply Fix
- Saving
fftSize/fftFpsin the admin panel now immediately applies to the running FFT processor - Root cause: pointer aliasing —
d.profileand the updated config were the same pointer, so the old/new comparison was always equal. Fixed by unconditionally rebuildingFftProcessoronSwitchProfile.
Other Fixes
- Fixed 50 Hz ticking / rumbling on ADPCM and raw IQ codecs —
updateResampleRatio()was called on every frame, resettingresamplePhaseat 50 Hz. Now only called when sample rate actually changes. stereoEnabledpropagated toOpusPipelineat construction so first packets use correct channel countws.ClientdefaultsStereoEnabled = trueso mono pipeline is never built before client sends preference- All mode-change filter state leaks fixed:
rumbleFilter,autoNotch,hiBlendIIR delay lines cleared;softMuteGainreset;stereoDetectedstore flag cleared - 8 pre-existing TypeScript type errors resolved (clean build)