Skip to content

File wfm_sink.h

FileList > doppler > wfm > wfm_sink.h

Go to the source code of this file

NATS PUB sink for generated IQ (Phase B). More...

  • #include "doppler/clib_common.h"

Public Types

Type Name
typedef struct wfm_stream_sink wfm_stream_sink_t

Public Functions

Type Name
int dp_wfm_stream_sink_available (void)
1 if the real stream sink (libdoppler_stream) is linked, else 0 (the pure-C core links only the weak no-op stubs). wfmgen checks this before the --output nats:// path.
double dp_wfm_stream_sink_clip_fraction (const wfm_stream_sink_t * sink)
void dp_wfm_stream_sink_close (wfm_stream_sink_t * sink)
Close the sink and destroy the publisher.
DP_NODISCARD int dp_wfm_stream_sink_drain (wfm_stream_sink_t * sink, int timeout_ms)
Let everything already sent reach the server, then stop.
wfm_stream_sink_t * dp_wfm_stream_sink_open (const char * endpoint, int sample_type)
Open a stream sink (PUB) bound to a NATS subject.
double dp_wfm_stream_sink_peak (const wfm_stream_sink_t * sink)
DP_NODISCARD int dp_wfm_stream_sink_send (wfm_stream_sink_t * sink, const float _Complex * iq, size_t n, double fs, double fc)
Convert a cf32 block to the wire type and publish it.
DP_NODISCARD int dp_wfm_stream_sink_send_eos (wfm_stream_sink_t * sink)
Tell subscribers this stream has ended.
void dp_wfm_stream_sink_set_gain (wfm_stream_sink_t * sink, double gain)
void dp_wfm_stream_sink_track_clipping (wfm_stream_sink_t * sink, int on)

Detailed Description

Streams cf32 blocks (from synth or the composer) to a NATS subject using doppler's dp_pub_* wire layer (SIGS header, magic "SIGS"), converting to the requested wire sample type per block. This is the --output nats://… destination; a dp_sub_* receiver (e.g. native/examples/spectrum_analyzer) reads the stream.

Lifecycle: dp_wfm_stream_sink_open -> dp_wfm_stream_sink_send* -> dp_wfm_stream_sink_drain -> dp_wfm_stream_sink_close

wfm_stream_sink_t *s = dp_wfm_stream_sink_open("nats://127.0.0.1:4222/iq", 3); // ci16
if (dp_wfm_stream_sink_send(s, iq, 4096, 1e6, 2.4e9) != 0)
  fprintf(stderr, "block refused: it never left this process\n");
if (dp_wfm_stream_sink_drain(s, 0) != 0)
  fprintf(stderr, "the tail may not have reached the server\n");
dp_wfm_stream_sink_close(s);

Public Types Documentation

typedef wfm_stream_sink_t

typedef struct wfm_stream_sink wfm_stream_sink_t;

Opaque stream sink.


Public Functions Documentation

function dp_wfm_stream_sink_available

1 if the real stream sink (libdoppler_stream) is linked, else 0 (the pure-C core links only the weak no-op stubs). wfmgen checks this before the --output nats:// path.

int dp_wfm_stream_sink_available (
    void
) 


function dp_wfm_stream_sink_clip_fraction

double dp_wfm_stream_sink_clip_fraction (
    const wfm_stream_sink_t * sink
) 

Fraction (0..1) of integer I/Q components that saturated; 0 unless tracked. The generated StreamSink handle binds peak/clip_fraction directly as per-field getters (jm#320), so no stats-snapshot struct shim is needed.


function dp_wfm_stream_sink_close

Close the sink and destroy the publisher.

void dp_wfm_stream_sink_close (
    wfm_stream_sink_t * sink
) 

Best-effort on its own: the client flushes what is still buffered for at most 500 ms and reports nothing, so a tail it cannot push out in that time is dropped silently. Call dp_wfm_stream_sink_drain() first on any run whose tail matters; close is then just the free.

Parameters:

  • sink May be NULL.

function dp_wfm_stream_sink_drain

Let everything already sent reach the server, then stop.

DP_NODISCARD int dp_wfm_stream_sink_drain (
    wfm_stream_sink_t * sink,
    int timeout_ms
) 

A send hands a block to the NATS client and returns; the client writes it in the background. So "send returned" is not "the server has it", and closing without asking relies on the client's own best-effort flush capped at 500 ms, with no way to report failure, so a backlog that cannot clear in half a second is dropped silently.

Call this before closing the sink on any run whose tail matters. After it returns the sink is finished: close it next, which is then just the free.

Parameters:

  • sink Sink; NULL is DP_OK (nothing was buffered).
  • timeout_ms Budget; <= 0 uses the stream layer's 5 s default.

Returns:

DP_OK once drained, or the stream layer's error DP_ERR_TIMEOUT if the budget ran out with the drain still in progress, in which case the sink is still safe to close.


function dp_wfm_stream_sink_open

Open a stream sink (PUB) bound to a NATS subject.

wfm_stream_sink_t * dp_wfm_stream_sink_open (
    const char * endpoint,
    int sample_type
) 

Parameters:

  • endpoint Endpoint, e.g. "nats://127.0.0.1:4222/iq".
  • sample_type Wire type (wavegen order): 0 cf32, 1 cf64, 2 ci32, 3 ci16, 4 ci8. Integer types use full-scale ±1.0.

Returns:

Sink handle, or NULL on bad type / publisher-create failure.

Note:

Caller must dp_wfm_stream_sink_close() when done.


function dp_wfm_stream_sink_peak

double dp_wfm_stream_sink_peak (
    const wfm_stream_sink_t * sink
) 

Largest per-axis magnitude seen on an integer path (pre-clip, full-scale 1).

1.0 ⇒ clipped; peak_dBFS = 20*log10(peak).


function dp_wfm_stream_sink_send

Convert a cf32 block to the wire type and publish it.

DP_NODISCARD int dp_wfm_stream_sink_send (
    wfm_stream_sink_t * sink,
    const float _Complex * iq,
    size_t n,
    double fs,
    double fc
) 

A refused block never left this process: the client refuses publishes while a reconnect has 8 MiB pending, and a drained sink refuses outright. The stream goes on, so the next block may go; a caller that keeps sending counts the refusals and reports them, as wfmgen does (#2011).

Parameters:

  • sink The sink handle.
  • iq Complex-float samples.
  • n Complex sample count.
  • fs Sample rate (Hz), carried in the wire header.
  • fc Center frequency (Hz), carried in the wire header.

Returns:

0 on success, non-zero on a refused send or an allocation error.


function dp_wfm_stream_sink_send_eos

Tell subscribers this stream has ended.

DP_NODISCARD int dp_wfm_stream_sink_send_eos (
    wfm_stream_sink_t * sink
) 

Publishes an end-of-stream frame, so a consumer learns the sender finished rather than inferring it from silence. Send it BEFORE draining: a drain cannot be reversed and refuses sends once it reaches its publish-flushing phase.

Parameters:

  • sink Sink; NULL is DP_OK (there is no stream to end).

Returns:

DP_OK, or the stream layer's error.


function dp_wfm_stream_sink_set_gain

void dp_wfm_stream_sink_set_gain (
    wfm_stream_sink_t * sink,
    double gain
) 

Set the output gain (linear; default 1.0). For headroom H dB pass 10^(−H/20). gain 1.0 sends cf32 unscaled (the direct path).


function dp_wfm_stream_sink_track_clipping

void dp_wfm_stream_sink_track_clipping (
    wfm_stream_sink_t * sink,
    int on
) 

Enable the per-component clip counter (off by default; peak always on).



The documentation for this class was generated from the following file native/inc/doppler/wfm/wfm_sink.h