Overview
Implement DAX IQ streaming to provide raw I/Q sample data to third-party SDR applications (SDR#, SDR Console, GQRX, GNU Radio, SpectraVue). Unlike regular DAX which carries demodulated audio, DAX IQ provides the unprocessed complex signal directly from the radio's DDC before any mode/filter/AGC processing.
Use Cases
- SDR software: Run SDR# or GQRX alongside AetherSDR for independent demodulation
- IQ recording: Record raw IQ for later playback and analysis
- Signal analysis: Feed GNU Radio or custom DSP pipelines
- Wide-band monitoring: Capture up to 192 kHz of spectrum
Protocol Details (from FlexLib DAXIQStream.cs)
VITA-49 Packet Class Codes
| PCC |
Sample Rate |
Bandwidth |
Payload |
0x02E3 |
24 kHz |
~24 kHz |
float32 I/Q interleaved, big-endian |
0x02E4 |
48 kHz |
~48 kHz |
float32 I/Q interleaved, big-endian |
0x02E5 |
96 kHz |
~96 kHz |
float32 I/Q interleaved, big-endian |
0x02E6 |
192 kHz |
~192 kHz |
float32 I/Q interleaved, big-endian |
Payload format: [I0, Q0, I1, Q1, ...] — each sample is two float32 values (8 bytes per I/Q pair). Values are big-endian and scaled by 1.0 / 2^15.
Commands
# Create IQ stream on channel 1
stream create type=dax_iq daxiq_channel=1
# Change sample rate (after creation)
stream set 0x<streamid> daxiq_rate=96000
# Remove stream
stream remove 0x<streamid>
Status Messages
S<handle>|stream <streamid> type=dax_iq daxiq_channel=1 pan=0x40000000 daxiq_rate=24000 client_handle=0x1234 active=1
Key fields: daxiq_channel (1-4), pan (associated panadapter), daxiq_rate (current sample rate), active (streaming).
Implementation Plan
Phase 1: Core IQ Stream Support
New: src/models/DaxIqModel.h/.cpp
- Per-channel IQ stream state: stream ID, channel (1-4), sample rate, pan ID, active
createStream(int channel) → stream create type=dax_iq daxiq_channel=N
setSampleRate(int rate) → stream set ... daxiq_rate=N
removeStream() → stream remove ...
- Parses status updates for
type=dax_iq streams
- Signals:
iqDataReady(int channel, const QByteArray& iqData, int sampleRate)
Modified: src/core/PanadapterStream.cpp
- Add PCC 0x02E3–0x02E6 to the packet router
- Register IQ stream IDs (similar to existing
registerDaxStream)
- Byte-swap float32 pairs and emit
iqDataReady(channel, data, rate)
- Multi-Flex filtering: only process IQ streams matching our
client_handle
Modified: src/models/RadioModel.cpp
- Parse
stream status for type=dax_iq → route to DaxIqModel
- Create/remove IQ streams on DAX IQ enable/disable
- Track IQ stream IDs for VITA-49 routing
Phase 2: Virtual Audio Devices (IQ output)
Modified: src/core/PipeWireAudioBridge.h/.cpp (Linux)
- Add 4 IQ pipe sources: "AetherSDR IQ 1-4"
- IQ channels use stereo (I=left, Q=right) — this is the one valid use of stereo in DAX
- Variable sample rate per channel (24k/48k/96k/192k) — set at pipe creation time
- Format: float32 stereo (not int16 mono like audio DAX)
macOS: src/core/VirtualAudioBridge.cpp
- Same pattern: 4 IQ virtual devices via CoreAudio HAL plugin
Phase 3: GUI
Modified: src/gui/CatApplet.cpp
- Add "DAX IQ" section below existing DAX channels
- 4 IQ channel enable/disable buttons
- Sample rate dropdown per channel: 24k / 48k / 96k / 192k
- Level meters showing IQ signal activity
Modified: src/gui/VfoWidget.cpp or RxApplet.cpp
- Add
dax_iq_channel selector (which IQ channel this slice feeds)
- Separate from the existing
dax channel selector
Phase 4: Compatibility
- SDR# / SDR Console: Expect audio devices with I=left, Q=right at specified sample rate. Our PipeWire stereo IQ source provides exactly this.
- GNU Radio: Can use
audio.source block pointing at the PipeWire device
- GQRX: Supports PulseAudio input with I/Q format
Data Flow
Radio DDC → VITA-49 UDP (PCC 0x02E3-0x02E6)
→ PanadapterStream: byte-swap float32, route by stream ID
→ DaxIqModel: emit iqDataReady(channel, data, rate)
→ PipeWireAudioBridge: write float32 stereo to IQ pipe
→ SDR app reads from "AetherSDR IQ N" capture device
Files Summary
| File |
Action |
src/models/DaxIqModel.h/.cpp |
NEW — IQ stream state, commands, status parsing |
src/core/PanadapterStream.h/.cpp |
Modify — add PCC 0x02E3-0x02E6 routing |
src/core/PipeWireAudioBridge.h/.cpp |
Modify — add 4 IQ stereo float32 pipe sources |
src/core/VirtualAudioBridge.h/.cpp |
Modify — add 4 IQ devices (macOS) |
src/models/RadioModel.cpp |
Modify — IQ stream lifecycle |
src/gui/CatApplet.cpp |
Modify — IQ channel controls |
CMakeLists.txt |
Modify — add DaxIqModel |
Capacity Considerations
The radio has a fixed number of DAX IQ channels (daxiq_capacity and daxiq_available reported in radio status). Higher sample rates consume more radio DDC resources. At 192 kHz, each IQ channel uses significant USB/network bandwidth (~1.5 MB/s per channel).
Dependencies
- Regular DAX (audio) must be working first (done)
- Multi-Flex IQ stream filtering by
client_handle (reuse existing pattern)
- No external library dependencies — all VITA-49 parsing is in-house
Overview
Implement DAX IQ streaming to provide raw I/Q sample data to third-party SDR applications (SDR#, SDR Console, GQRX, GNU Radio, SpectraVue). Unlike regular DAX which carries demodulated audio, DAX IQ provides the unprocessed complex signal directly from the radio's DDC before any mode/filter/AGC processing.
Use Cases
Protocol Details (from FlexLib DAXIQStream.cs)
VITA-49 Packet Class Codes
0x02E30x02E40x02E50x02E6Payload format:
[I0, Q0, I1, Q1, ...]— each sample is two float32 values (8 bytes per I/Q pair). Values are big-endian and scaled by1.0 / 2^15.Commands
Status Messages
Key fields:
daxiq_channel(1-4),pan(associated panadapter),daxiq_rate(current sample rate),active(streaming).Implementation Plan
Phase 1: Core IQ Stream Support
New:
src/models/DaxIqModel.h/.cppcreateStream(int channel)→stream create type=dax_iq daxiq_channel=NsetSampleRate(int rate)→stream set ... daxiq_rate=NremoveStream()→stream remove ...type=dax_iqstreamsiqDataReady(int channel, const QByteArray& iqData, int sampleRate)Modified:
src/core/PanadapterStream.cppregisterDaxStream)iqDataReady(channel, data, rate)client_handleModified:
src/models/RadioModel.cppstreamstatus fortype=dax_iq→ route to DaxIqModelPhase 2: Virtual Audio Devices (IQ output)
Modified:
src/core/PipeWireAudioBridge.h/.cpp(Linux)macOS:
src/core/VirtualAudioBridge.cppPhase 3: GUI
Modified:
src/gui/CatApplet.cppModified:
src/gui/VfoWidget.cpporRxApplet.cppdax_iq_channelselector (which IQ channel this slice feeds)daxchannel selectorPhase 4: Compatibility
audio.sourceblock pointing at the PipeWire deviceData Flow
Files Summary
src/models/DaxIqModel.h/.cppsrc/core/PanadapterStream.h/.cppsrc/core/PipeWireAudioBridge.h/.cppsrc/core/VirtualAudioBridge.h/.cppsrc/models/RadioModel.cppsrc/gui/CatApplet.cppCMakeLists.txtCapacity Considerations
The radio has a fixed number of DAX IQ channels (
daxiq_capacityanddaxiq_availablereported in radio status). Higher sample rates consume more radio DDC resources. At 192 kHz, each IQ channel uses significant USB/network bandwidth (~1.5 MB/s per channel).Dependencies
client_handle(reuse existing pattern)