|
|
1 mese fa | |
|---|---|---|
| cmd | 1 mese fa | |
| docs | 1 mese fa | |
| examples | 1 mese fa | |
| internal | 1 mese fa | |
| libiio | 1 mese fa | |
| scripts | 1 mese fa | |
| .gitignore | 1 mese fa | |
| CHANGELOG.md | 1 mese fa | |
| PROJECT_PLAN.md | 1 mese fa | |
| README.md | 1 mese fa | |
| RELEASE.md | 1 mese fa | |
| fm-rds-tx_pro_runtime_hardening_concept.json | 1 mese fa | |
| go.mod | 1 mese fa | |
| go.sum | 1 mese fa | |
| stream_tx.bat | 1 mese fa | |
Go-based FM stereo transmitter with RDS. Supports ADALM-Pluto (PlutoSDR) and SoapySDR-compatible TX devices.
Current status: v0.9.0 — runtime hardening milestone
What is already in place:
/stdin, http-raw, and icecastauto/native/ffmpeg)Current engineering focus:
mp3/oggvorbis/aac are placeholders; ffmpeg fallback is the currently functional decode path)For the active runtime-hardening track, see:
docs/pro-runtime-hardening-workboard.mdAudio Source -> PreEmphasis(50us/75us/off) -> StereoEncoder(19k + 38k DSB-SC)
-> RDS(57k BPSK) -> MPX Combiner -> Limiter -> FM Modulator(+/-75kHz)
-> optional split-rate FM upsampling -> SDR backend -> RF output
For deeper DSP details, see:
docs/DSP-CHAIN.mdgo.mod (currently Go 1.22)Depending on backend, native libraries are required:
SoapySDR backend
-tags soapySoapySDR.dll / libSoapySDR.so / libSoapySDR.dylib)Pluto backend
libiiolibiio.dllpkg-config + libiio# Build CLI tools without hardware-specific build tags:
go build ./cmd/fmrtx
go build ./cmd/offline
# Build fmrtx with SoapySDR support:
go build -tags soapy ./cmd/fmrtx
# Print effective config
go run ./cmd/fmrtx -print-config
# Run tests
go test ./...
# Basic dry-run summary
go run ./cmd/fmrtx --dry-run --dry-output build/dryrun/frame.json
For additional build/test commands, see:
docs/README.md.\fmrtx.exe --list-devices
.\fmrtx.exe --dry-run --dry-output build/dryrun/frame.json
# Write dry-run JSON to stdout
.\fmrtx.exe --dry-run --dry-output -
go run ./cmd/offline -duration 2s -output build/offline/composite.iqf32
# Optional output rate override
go run ./cmd/offline -duration 500ms -output build/offline/composite.iqf32 -output-rate 228000
go run ./cmd/fmrtx --simulate-tx --simulate-output build/sim/simulated-soapy.iqf32 --simulate-duration 250ms
# Start TX service with manual start over HTTP
.\fmrtx.exe --tx --config docs/config.plutosdr.json
# Start and begin transmitting immediately
.\fmrtx.exe --tx --tx-auto-start --config docs/config.plutosdr.json
ffmpeg -i "http://svabi.ch:8443/stream" -f s16le -ar 44100 -ac 2 - | .\fmrtx.exe --tx --tx-auto-start --audio-stdin --config docs/config.plutosdr.json
ffmpeg -i source.wav -f s16le -ar 48000 -ac 2 - | .\fmrtx.exe --tx --tx-auto-start --audio-stdin --audio-rate 48000 --config docs/config.plutosdr.json
Start the control plane with --audio-http to accept raw PCM pushes on /audio/stream and feed them into the live encoder:
Set Content-Type to application/octet-stream (or audio/L16) when posting audio data:
ffmpeg -i music.mp3 -f s16le -ar 44100 -ac 2 - | curl -X POST -H "Content-Type: application/octet-stream" --data-binary @- http://localhost:8088/audio/stream
Use ingest.kind = "icecast" and set ingest.icecast.url in config.
Decoder semantics in Phase 1:
ingest.icecast.decoder = "auto": try native by content-type, fallback to ffmpeg on unsupported pathsingest.icecast.decoder = "native": native only, no fallbackingest.icecast.decoder = "ffmpeg" (or fallback): ffmpeg onlyCurrent implementation note: native codec packages exist but are placeholders; practical decode today is ffmpeg fallback.
fmrtxImportant runtime modes and flags include:
--tx--tx-auto-start--dry-run--dry-output <path|- >--simulate-tx--simulate-output <path>--simulate-duration <duration>--config <path>--print-config--list-devices--audio-stdin--audio-rate <hz>--audio-httpofflineUseful flags include:
-duration <duration>-output <path>-output-rate <hz>If the README is too high-level for the exact CLI surface, check:
cmd/fmrtx/main.gocmd/offline/main.goBase URL: http://{listenAddress} (default typically 127.0.0.1:8088)
Security note:
GET / browser UI
GET /healthz health check
GET /status current config/status snapshot
GET /runtime live engine / driver / audio telemetry
GET /config full config
POST /config patch config / live updates
GET /dry-run synthetic frame summary
POST /tx/start start transmission
POST /tx/stop stop transmission
POST /audio/stream push raw S16LE stereo PCM into live stream buffer (Content-Type: application/octet-stream or audio/L16 required)
--audio-http)POST /config supports live updates for selected fields such as:
Some parameters are saved but not live-applied and require restart.
For the full API contract, examples, live-patch semantics, and /audio/stream details, see:
docs/API.mdSample configs:
docs/config.sample.jsondocs/config.plutosdr.jsondocs/config.orangepi-pluto-soapy.jsonImportant config areas include:
fm.*rds.*audio.*backend.*control.*ingest.*Examples of relevant fields you may want to inspect:
fm.outputDrivefm.mpxGainfm.bs412Enabledfm.bs412ThresholdDBrfm.fmModulationEnabledbackend.kindbackend.driverbackend.deviceArgsbackend.uribackend.deviceSampleRateHzbackend.outputPathcontrol.listenAddressFor deeper config/API behavior, refer to:
internal/config/config.godocs/API.mddocs/config.sample.jsonUseful commands:
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
See also:
docs/README.mdcmd/
fmrtx/ main CLI
offline/ offline generator
internal/
app/ TX engine + runtime state
audio/ audio input, resampling, tone generation, stream buffering
config/ config schema and validation
control/ HTTP control plane + browser UI
dryrun/ dry-run JSON summaries
dsp/ DSP primitives
mpx/ MPX combiner
offline/ full offline composite generation
output/ output/backend abstractions
platform/ backend abstractions and device/runtime stats
platform/soapysdr/ CGO SoapySDR binding
platform/plutosdr/ Pluto/libiio backend code
rds/ RDS encoder
stereo/ stereo encoder
docs/
API.md
DSP-CHAIN.md
README.md
config.sample.json
config.plutosdr.json
config.orangepi-pluto-soapy.json
pro-runtime-hardening-workboard.md
scripts/
examples/
For the current runtime-hardening / professionalization track, see:
docs/pro-runtime-hardening-workboard.mdThis is the living workboard for:
Additional project docs:
CHANGELOG.mdRELEASE.mddocs/README.mddocs/API.mddocs/DSP-CHAIN.mddocs/NOTES.mdThis project is intended only for lawful use within relevant license and regulatory constraints. RF output, deviation, filtering, and transmitted power must be validated with proper measurement equipment.