Go-based FM stereo transmitter with RDS, Windows-first and cross-platform
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
Jan d2d80bd0d5 docs: describe WS-1 telemetry and tighten UI measurement source 4週間前
..
Logo Brand control UI with ferrite.fm logo 1ヶ月前
rds-standards feat(rds2): add LPS, eRT and RDS2 controls 1ヶ月前
API.md docs: describe WS-1 telemetry and tighten UI measurement source 4週間前
DSP-CHAIN.md fix(ui): clarify limiter behavior and active radio text 1ヶ月前
Kim_-_Parikh_-_Distribution_of_the_Analog_or_Digital_FM_Composite.pdf docs: add composite/MPX live metering concept and reference material 1ヶ月前
NOTES.md docs: bootstrap fm rds transmitter project plan 1ヶ月前
README.md release: bump version to 0.9.0 1ヶ月前
audio-ingest-implementation-plan.md docs(ingest): align phase-1 status and decoder fallback semantics 1ヶ月前
audio-ingest-rework.md docs: record ingest rework status and refresh plutosdr example config 1ヶ月前
composite-mpx-metering-concept.json docs: add composite/MPX live metering concept and reference material 1ヶ月前
composite-mpx-metering-concept.md docs: add composite/MPX live metering concept and reference material 1ヶ月前
config.orangepi-pluto-soapy.json feat: add Linux PlutoSDR support and Orange Pi build tooling 1ヶ月前
config.plutosdr.json Update PlutoSDR example config defaults 1ヶ月前
config.sample.json docs(ingest): align phase-1 status and decoder fallback semantics 1ヶ月前
metering-ws1-implementation-plan.md feat: add WS-1 metering telemetry and calmer meter holds 1ヶ月前
metering_telemetry_autobahn_v3.md feat: add WS-1 metering telemetry and calmer meter holds 1ヶ月前
pro-runtime-hardening-workboard.md docs: reconcile workboard and runtime API status 1ヶ月前
ui-flow-view-sollmodell.md Add ferrite.fm flow view MVP and design model 1ヶ月前
ui-rework-sollmodell.md docs: add UI rework sollmodell 1ヶ月前
ws-03-parameter-inventory.md feat: document WS-03 parameters and align outputDrive validation 1ヶ月前

README.md

fm-rds-tx docs

Build & Test

Root CLI

  • go test ./...
  • go run ./cmd/fmrtx -print-config
  • go run ./cmd/fmrtx -config docs/config.sample.json
  • go run ./cmd/fmrtx --dry-run --dry-output build/dryrun/frame.json
  • go run ./cmd/fmrtx --simulate-tx --simulate-output build/sim/simulated-soapy.iqf32 --simulate-duration 250ms
  • go run ./cmd/offline -duration 500ms -output build/offline/composite.iqf32

Audio source modes

Current no-hardware sources:

  • generated stereo tones via config
  • 16-bit PCM WAV file input via audio.inputPath (robust chunk-scanning loader)
  • linear-interpolation sample-rate conversion for WAV sources
  • transparent tone fallback if the configured WAV source cannot be loaded

Tone configuration

The current no-hardware source can be parameterized via config:

  • audio.toneLeftHz
  • audio.toneRightHz
  • audio.toneAmplitude

DSP chain

The full signal chain from audio input to IQ output:

  1. Audio ingest — tone generator or WAV file with linear-interpolation resampler
  2. Gain staging — configurable audio gain
  3. Pre-emphasis — first-order IIR high-shelf filter, configurable τ (50 µs EU / 75 µs US / 0 = off)
  4. Stereo encoder — L+R mono, L-R on stateful 38 kHz DSB-SC subcarrier, phase-coherent 19 kHz pilot
  5. RDS encoder — standards-grade group framing (0A/2A), CRC-10 per IEC 62106, differential encoding, 57 kHz BPSK subcarrier, group scheduler cycling PS and RadioText
  6. MPX combiner — configurable gains for mono, stereo, pilot, and RDS components
  7. Output drive — configurable output level scaling
  8. MPX limiter — smooth attack/release peak limiter with hard-clip safety net
  9. FM modulator — composite-to-IQ via phase integration, configurable ±75 kHz deviation, unit-magnitude IQ output

Pre-emphasis

FM broadcast requires pre-emphasis to boost high frequencies before transmission. The receiver applies complementary de-emphasis to restore flat response while reducing noise.

  • Europe/World: τ = 50 µs (preEmphasisUS: 50)
  • North America/South Korea: τ = 75 µs (preEmphasisUS: 75)
  • Disabled: preEmphasisUS: 0

FM modulation modes

  • fmModulationEnabled: true — output is baseband FM-modulated IQ (I² + Q² = 1). This is what SDR transmitters expect.
  • fmModulationEnabled: false — output is raw composite MPX (I = composite, Q = 0). Useful for analysis or composite exciters.

Split-rate mode (Pluto / HackRF)

When deviceSampleRateHz > compositeRateHz (e.g. Pluto at 2.28 MHz, composite at 228 kHz), the engine automatically activates split-rate mode:

  1. DSP chain (stereo, RDS, limiter) runs at compositeRateHz (228 kHz)
  2. FMUpsampler performs FM modulation + phase-domain interpolation to deviceSampleRateHz
  3. Hardware receives IQ at device rate

This halves CPU load compared to running all DSP at device rate. Log output confirms the active mode:

engine: split-rate mode — DSP@228000Hz → upsample@2280000Hz (ratio 10.00)

When rates are equal (e.g. LimeSDR at 228 kHz), same-rate mode is used:

engine: same-rate mode — DSP@228000Hz

Limiter

The MPX limiter prevents overmodulation by applying smooth gain reduction when the composite signal exceeds the configured ceiling. A hard clipper acts as a safety net after the limiter.

  • limiterEnabled: true/false
  • limiterCeiling: 1.0 (max composite level before FM modulation)

HTTP control surface

Full API documentation: docs/API.md

All major TX parameters are hot-reloadable via POST /config during live transmission — frequency, stereo/mono, RDS text, output drive, pilot/RDS levels, limiter. Changes take effect within 50–88ms without stopping the stream.

Available endpoints: /healthz, /status, /runtime, /config (GET/POST), /dry-run, /tx/start, /tx/stop

Control-plane HTTP server is configured with 5s read, 10s write, and 60s idle timeouts plus a 1 MiB header limit to reduce slow-client abuse.

Internal DSP module

  • cd internal
  • go test ./...

Examples module

  • cd examples
  • go test ./...
  • go run ./soapy_simulated

Dry run

The dry-run mode generates a synthetic, hardware-free frame summary based on the current config. It reports the active source label, pre-emphasis setting, limiter state, and FM modulation mode.

The HTTP control plane also exposes GET /dry-run for quick inspection.

Simulated transmit

--simulate-tx runs the offline generator through the Soapy-oriented simulated backend path and writes an IQ-style artifact to disk.

Offline generation

cmd/offline generates a deterministic no-hardware IQ/composite file using the full DSP chain (pre-emphasis, stereo encoding, RDS, limiter, FM modulation).

Release posture

Current honest release posture: pre-v1. Recommended milestone tag: v0.9.0. See CHANGELOG.md and RELEASE.md.