LuaRadio Reference Manual

Generated from LuaRadio v0.5.0.

Table of contents

Example

local radio = require('radio')

-- RTL-SDR Source, frequency 88.5 MHz - 250 kHz, sample rate 1102500 Hz
local source = radio.RtlSdrSource(88.5e6 - 250e3, 1102500)
-- Tuner block, translate -250 kHz, filter 200 kHz, decimate by 5
local tuner = radio.TunerBlock(-250e3, 200e3, 5)
-- Wideband FM Stereo Demodulator block
local demodulator = radio.WBFMStereoDemodulator()
-- Left and right AF downsampler blocks
local l_downsampler = radio.DownsamplerBlock(5)
local r_downsampler = radio.DownsamplerBlock(5)
-- Audio sink, 2 channels for left and right audio
local sink = radio.PulseAudioSink(2)
-- Top-level block
local top = radio.CompositeBlock()

-- Connect blocks in top block
top:connect(source, tuner, demodulator)
top:connect(demodulator, 'left', l_downsampler, 'in')
top:connect(demodulator, 'right', r_downsampler, 'in')
top:connect(l_downsampler, 'out', sink, 'in1')
top:connect(r_downsampler, 'out', sink, 'in2')

-- Run top block
top:run()
$ luaradio example.lua

Running

LuaRadio scripts can be run with the luaradio runner, or directly with luajit, if the radio package is installed in your Lua path.

luaradio runner

The luaradio runner is a simple wrapper script for running LuaRadio scripts. It can also print version information, dump relevant platform information, and adjust the runtime debug verbosity of scripts. The runner modifies the Lua path to support importing the radio package locally, so it can be used to run LuaRadio scripts directly from the repository without installation.

$ ./luaradio
Usage: luaradio [options] <script> [args]

Options:
   -h, --help      Print help and exit
   --version       Print version and exit
   --platform      Dump platform and exit
   -v, --verbose   Enable debug verbosity
$

To run a script, use luaradio as you would use luajit:

$ luaradio script.lua

To run a script with debug verbosity:

$ luaradio -v script.lua

Environment Variables

LuaRadio interprets several environment variables to adjust runtime settings. These environment variables are treated as flags that can be enabled with value 1 (or values y, yes, true).

  • LUARADIO_DEBUG - Enable debug verbosity
  • LUARADIO_DISABLE_LIQUID - Disable liquid-dsp library
  • LUARADIO_DISABLE_VOLK - Disable volk library
  • LUARADIO_DISABLE_FFTW3F - Disable fftw3f library

For example, to enable debug verbosity:

$ LUARADIO_DEBUG=1 luaradio script.lua

To disable use of the VOLK library:

$ LUARADIO_DISABLE_VOLK=1 luaradio script.lua

To run a script with no external libraries for acceleration:

$ LUARADIO_DISABLE_LIQUID=1 LUARADIO_DISABLE_VOLK=1 LUARADIO_DISABLE_FFTW3F=1 luaradio script.lua

Blocks

Composition

CompositeBlock

radio.CompositeBlock()

Create a block to hold a flow graph composition, for either top-level or hierarchical purposes. Top-level blocks may be run with the run() method.

CompositeBlock:connect(...)

Connect blocks.

This method can be used in three ways:

Linear block connections. Connect the first output to the first input of each adjacent block. This usage is convenient for connecting blocks that only have one input port and output port (which is most blocks).

top:connect(b1, b2, b3)

Explicit block connections. Connect a particular output of the first block to a particular input of the second block. The output and input ports are specified by name. This invocation is used to connect a block to another block with multiple input ports.

top:connect(b1, 'out', b2, 'in2')

Alias port connections. Alias a composite block’s input or output port to a concrete block’s input or output port. This invocation is used for connecting the boundary inputs and outputs of a hierarchical block.

function MyHierarchicalBlock:instantiate()
    local b1, b2, b3 = ...

    ...

    self:connect(b1, b2, b3)

    self:connect(self, 'in', b1, 'in')
    self:connect(self, 'out', b3, 'out')
end
Arguments
  • ...: Blocks [and ports] to connect
Returns
  • self (CompositeBlock)
Raises
  • Output port of block not found error.
  • Input port of block not found error.
  • Input port of block already connected error.
CompositeBlock:run()

Run a top-level block. This is equivalent to calling start() followed by wait() on the top-level block.

Returns
  • self (CompositeBlock)
Raises
  • Block already running error.
  • Block input port unconnected error.
  • Block input port sample rate mismatch error.
  • No compatible type signatures found for block error.
Example
-- Run a top-level block
top:run()
CompositeBlock:start()

Start a top-level block.

Returns
  • self (CompositeBlock)
Raises
  • Block already running error.
  • Block input port unconnected error.
  • Block input port sample rate mismatch error.
  • No compatible type signatures found for block error.
Example
-- Start a top-level block
top:start()
CompositeBlock:status()

Get the status of a top-level block.

Returns
  • Status information with fields: running (bool). (table)
Example
if top:status().running then
    print('Still running...')
end
CompositeBlock:stop()

Stop a top-level block and wait until it has finished.

Example
-- Start a top-level block
top:start()
-- Stop a top-level block
top:stop()
CompositeBlock:wait()

Wait for a top-level block to finish, either by natural termination or by SIGINT.

Example
-- Start a top-level block
top:start()
-- Wait for the top-level block to finish
top:wait()

Sources

AirspySource

Source a complex-valued signal from an Airspy. This source requires the libairspy library. The Airspy R2 and Airspy Mini dongles are supported.

radio.AirspySource(frequency, rate[, options={}])
Arguments
  • frequency (number): Tuning frequency in Hz
  • rate (number): Sample rate in Hz (3 MHz or 6 MHz for Airspy Mini, 2.5 MHz or 10 MHz for Airspy R2)
  • options (table): Additional options, specifying:
    • gain_mode (string, default “linearity”, choice of “custom”, “linearity”, “sensitivity”)
    • lna_gain (int, default 5 dB, for custom gain mode, range 0 to 15 dB)
    • mixer_gain (int, default 1 dB, for custom gain mode, range 0 to 15 dB)
    • vga_gain (int, default 5 dB, for custom gain mode, range 0 to 15 dB)
    • lna_agc (bool, default false, for custom gain mode)
    • mixer_agc (bool, default false, for custom gain mode)
    • linearity_gain (int, default 10, for linearity gain mode, range 0 to 21)
    • sensitivity_gain (int, default 10, for sensitivity gain mode, range 0 to 21)
    • biastee_enable (bool, default false)
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source samples from 135 MHz sampled at 6 MHz
local src = radio.AirspySource(135e6, 6e6)

-- Source samples from 91.1 MHz sampled at 3 MHz, with custom gain settings
local src = radio.AirspySource(91.1e6, 3e6, {gain_mode = "custom", lna_gain = 4,
                                             mixer_gain = 1, vga_gain = 6})

-- Source samples from 91.1 MHz sampled at 2.5 MHz, with linearity gain mode
local src = radio.AirspySource(91.1e6, 2.5e6, {gain_mode = "linearity", linearity_gain = 8})

-- Source samples from 91.1 MHz sampled at 2.5 MHz, with sensitivity gain mode
local src = radio.AirspySource(91.1e6, 2.5e6, {gain_mode = "sensitivity", sensitivity_gain = 8})

-- Source samples from 144.390 MHz sampled at 2.5 MHz, with bias tee enabled
local src = radio.AirspySource(144.390e6, 2.5e6, {biastee_enable = true})

HackRFSource

Source a complex-valued signal from a HackRF One. This source requires the libhackrf library.

radio.HackRFSource(frequency, rate[, options={}])
Arguments
  • frequency (number): Tuning frequency in Hz
  • rate (number): Sample rate in Hz
  • options (table): Additional options, specifying:
    • lna_gain (int, default 8 dB, range 0 to 40 dB, 8 dB step)
    • vga_gain (int, default 40 dB, range 0 to 62 dB, 2 dB step)
    • bandwidth (number in Hz, default round down from sample rate)
    • rf_amplifier_enable (bool, default false)
    • antenna_power_enable (bool, default false)
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source samples from 135 MHz sampled at 10 MHz
local src = radio.HackRFSource(135e6, 10e6)

-- Source samples from 135 MHz sampled at 10 MHz, with 2.5 MHz bandwidth
local src = radio.HackRFSource(135e6, 10e6, {bandwidth = 2.5e6})

-- Source samples from 91.1 MHz sampled at 8 MHz, with custom gain settings
local src = radio.HackRFSource(91.1e6, 8e6, {lna_gain = 16, vga_gain = 22})

-- Source samples from 144.390 MHz sampled at 8 MHz, with antenna power enabled
local src = radio.HackRFSource(144.390e6, 8e6, {antenna_power_enable = true})

IQFileSource

Source a complex-valued signal from a binary “IQ” file. The file format may be 8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big endianness, and interleaved as real component followed by imaginary component.

radio.IQFileSource(file, format, rate[, repeat_on_eof=false])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • format (string): File format specifying signedness, bit width, and endianness of samples. Choice of “s8”, “u8”, “u16le”, “u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”, “f32le”, “f32be”, “f64le”, “f64be”.
  • rate (number): Sample rate in Hz
  • repeat_on_eof (bool): Repeat on end of file
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source signed 8-bit IQ samples from a file sampled at 1 MHz
local src = radio.IQFileSource('samples.s8.iq', 's8', 1e6)

-- Source little-endian 32-bit IQ samples from a file sampled at 1 MHz, repeating on EOF
local src = radio.IQFileSource('samples.f32le.iq', 'f32le', 1e6, true)

-- Source little-endian signed 16-bit IQ samples from stdin sampled at 500 kHz
local src = radio.IQFileSource(io.stdin, 's16le', 500e3)

PulseAudioSource

Source one or more real-valued signals from the system’s audio device with PulseAudio. This source requires PulseAudio.

radio.PulseAudioSource(num_channels, rate)
Arguments
  • num_channels (int): Number of channels (e.g. 1 for mono, 2 for stereo)
  • rate (int): Sample rate in Hz
Type Signatures
  • ❑➔ out Float32
  • ❑➔ out1 Float32, out2 Float32
Example
-- Source one channel (mono) audio sampled at 44100 Hz
local src = radio.PulseAudioSource(1, 44100)

-- Source two channel (stereo) audio sampled at 48000 Hz
local src = radio.PulseAudioSource(2, 48000)
-- Compose the two channels into a complex-valued signal
local floattocomplex = radio.FloatToComplex()
top:connect(src, 'out1', floattocomplex, 'real')
top:connect(src, 'out2', floattocomplex, 'imag')
top:connect(floattocomplex, ...)

RawFileSource

Source a signal of the specified data type from a binary file. The raw binary samples are cast to the specified data type with no signedness conversion, endian conversion, or interpretation. This is useful for serializing data types across a pipe or other file descriptor based IPC.

radio.RawFileSource(file, data_type, rate[, repeat_on_eof=false])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • data_type (type): LuaRadio data type
  • rate (number): Sample rate of file
  • repeat_on_eof (bool): Repeat on end of file
Type Signatures
  • ❑➔ out data_type
Example
-- Source ComplexFloat32 samples sampled at 1 MHz from a file descriptor
local src = radio.RawFileSource(3, radio.types.ComplexFloat32, 1e6)

-- Source Byte samples sampled at 100 kHz from a file, repeating on EOF
local src = radio.RawFileSource('data.bin', radio.types.Byte, 100e3, true)

RealFileSource

Source a real-valued signal from a binary file. The file format may be 8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big endianness. This is the real-valued counterpart of IQFileSource.

radio.RealFileSource(file, format, rate[, repeat_on_eof=false])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • format (string): File format specifying signedness, bit width, and endianness of samples. Choice of “s8”, “u8”, “u16le”, “u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”, “f32le”, “f32be”, “f64le”, “f64be”.
  • rate (number): Sample rate in Hz
  • repeat_on_eof (bool): Repeat on end of file
Type Signatures
  • ❑➔ out Float32
Example
-- Source signed 8-bit real samples from a file sampled at 1 MHz
local src = radio.RealFileSource('samples.s8.real', 's8', 1e6)

-- Source little-endian 32-bit real samples from a file sampled at 1 MHz, repeating on EOF
local src = radio.RealFileSource('samples.f32le.real', 'f32le', 1e6, true)

-- Source little-endian signed 16-bit real samples from stdin sampled at 500 kHz
local src = radio.RealFileSource(0, 's16le', 500e3)

RtlSdrSource

Source a complex-valued signal from an RTL-SDR dongle. This source requires the librtlsdr library.

radio.RtlSdrSource(frequency, rate[, options={}])
Arguments
  • frequency (number): Tuning frequency in Hz
  • rate (number): Sample rate in Hz
  • options (table): Additional options, specifying:
    • autogain (bool, default false)
    • rf_gain (number, default closest supported to 10.0 dB)
    • freq_correction PPM (number, default 0.0)
    • device_index (integer, default 0)
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source samples from 162.400 MHz sampled at 1 MHz, with autogain enabled
local src = radio.RtlSdrSource(162.400e6, 1e6, {autogain = true})

-- Source samples from 91.1 MHz sampled at 1.102500 MHz, with -1 PPM correction
local src = radio.RtlSdrSource(91.1e6, 1102500, {freq_correction = -1.0})

-- Source samples from 144.390 MHz sampled at 1 MHz, with RF gain of 15dB
local src = radio.RtlSdrSource(144.390e6, 1e6, {rf_gain = 15.0})

SDRplaySource

Source a complex-valued signal from an SDRplay RSP. This source requires the libmirsdrapi-rsp library.

radio.SDRplaySource(frequency, rate[, options={}])
Arguments
  • frequency (number): Tuning frequency in Hz
  • rate (number): Sample rate in Hz
  • options (table): Additional options, specifying:
    • gain_reduction (int, default 80 dB, range of 0 to 102 dB)
    • bandwidth (number, default closest, choice of 0.200 MHz, 0.300 MHz, 0.600 MHz, 1.536 MHz, 5.000 MHz, 6.000 MHz, 7.000 MHz, 8.000 MHz)
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source samples from 91.1 MHz sampled at 2 MHz
local src = radio.SDRplaySource(91.1e6, 2e6)

-- Source samples from 144.390 MHz sampled at 4 MHz, with 0.6 MHz bandwidth
local src = radio.SDRplaySource(144.390e6, 4e6, {bandwidth = 0.6e6})

-- Source samples from 15 MHz sampled at 10 MHz, with 75 dB gain reduction
local src = radio.SDRplaySource(15e6, 10e6, {gain_reduction = 75})

SignalSource

Source a complex or real valued signal from a signal generator.

Note: the “exponential” waveform generates a complex-valued signal, all other waveform types generate a real-valued signal.

radio.SignalSource(signal, frequency, rate[, options={}])
Arguments
  • signal (string): Waveform type, either “exponential”, “cosine”, “sine”, “square”, “triangle”, “sawtooth”, “constant”.
  • frequency (number): Frequency in Hz
  • rate (number|nil): Sample rate in Hz
  • options (table): Additional options, specifying:
    • amplitude (number, default 1.0)
    • offset (number, default 0.0)
    • phase (number in radians, default 0.0)
Type Signatures
  • ❑➔ out ComplexFloat32
  • ❑➔ out Float32
Example
-- Source a 250 kHz complex exponential sampled at 2 MHz
local src = radio.SignalSource('exponential', 250e3, 2e6)

-- Source a 100 kHz cosine sampled at 1 MHz, with amplitude 2.5
local src = radio.SignalSource('cosine', 100e3, 1e6, {amplitude = 2.5})

-- Source a 1 kHz square wave sampled at 2 MHz, with offset 1.0
local src = radio.SignalSource('square', 1e3, 2e6, {offset = 1.0})

SoapySDRSource

Source a complex-valued signal from a SoapySDR device. This source requires SoapySDR.

radio.SoapySDRSource(driver, frequency, rate[, options={}])
Arguments
  • driver (string|table): Driver string or key-value table
  • frequency (number): Tuning frequency in Hz
  • rate (number): Sample rate in Hz
  • options (table): Additional options, specifying:
    • channel (int, default 0)
    • bandwidth (number in Hz)
    • autogain (bool)
    • antenna (string)
    • gain (number in dB, overall gain)
    • gains (table, gain element name to value in dB)
    • frequencies (table, frequency element name to value in Hz)
    • settings (table, string key-value pairs of driver-specific settings)
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source samples from an RTL-SDR at 91.1 MHz sampled at 1 MHz
local src = radio.SoapySDRSource("driver=rtlsdr", 91.1e6, 1e6)

-- Source samples from an Airspy at 15 MHz sampled at 6 MHz, with 10 dB overall gain
local src = radio.SoapySDRSource("driver=airspy", 15e6, 6e6, {gain = 10})

-- Source samples from a LimeSDR at 915 MHz sampled at 10 MHz,
-- with 20 dB overall gain and 4 MHz baseband bandwidth
local src = radio.SoapySDRSource("driver=limesdr", 915e6, 10e6, {gain = 20, bandwidth = 4e6})

-- Source samples from a HackRF at 144.390 MHz sampled at 8 MHz,
-- with 2.5 MHz baseband bandwidth
local src = radio.SoapySDRSource("driver=hackrf", 144.390e6, 8e6, {bandwidth = 2.5e6})

UHDSource

Source a complex-valued signal from a USRP. This source requires the libuhd library.

radio.UHDSource(device_address, frequency, rate[, options={}])
Arguments
  • device_address (string): Device address string
  • frequency (number): Tuning frequency in Hz
  • rate (number): Sample rate in Hz
  • options (table): Additional options, specifying:
    • channel (int, default 0)
    • gain (number in dB, overall gain, default 15.0 dB)
    • bandwidth (number in Hz)
    • antenna (string)
    • autogain (bool)
    • gains (table, gain element name to value in dB)
Type Signatures
  • ❑➔ out ComplexFloat32
Example
-- Source samples from a B200 at 91.1 MHz sampled at 2 MHz
local src = radio.UHDSource("type=b200", 91.1e6, 2e6)

-- Source samples from a B200 at 915 MHz sampled at 10 MHz, with 20 dB
-- overall gain
local src = radio.UHDSource("type=b200", 915e6, 10e6, {gain = 20})

-- Source samples from a B200 at 144.390 MHz sampled at 8 MHz, with 2.5 MHz
-- baseband bandwidth
local src = radio.UHDSource("type=b200", 144.390e6, 8e6, {bandwidth = 2.5e6})

UniformRandomSource

Source a signal with values drawn from a uniform random distribution.

radio.UniformRandomSource(data_type, rate[, range={}, options={}])
Arguments
  • data_type (type): LuaRadio data type, choice of radio.types.ComplexFloat32, radio.types.Float32, radio.types.Byte, or radio.types.Bit data types.
  • rate (number): Sample rate in Hz
  • range (array): Value range as an array, e.g {10, 100}.
  • options (table): Additional options, specifying:
    • seed (number)
Type Signatures
  • ❑➔ out ComplexFloat32
  • ❑➔ out Float32
  • ❑➔ out Byte
  • ❑➔ out Bit
Example
-- Source a random ComplexFloat32 signal sampled at 1 MHz
local src = radio.UniformRandomSource(radio.types.ComplexFloat32, 1e6)

-- Source a random Float32 signal sampled at 1 MHz
local src = radio.UniformRandomSource(radio.types.Float32, 1e6)

-- Source a random Byte signal sampled at 1 kHz, ranging from 65 to 90
local src = radio.UniformRandomSource(radio.types.Byte, 1e3, {65, 90})

-- Source a random bit stream sampled at 1 kHz
local src = radio.UniformRandomSource(radio.types.Bit, 1e3)

WAVFileSource

Source one or more real-valued signals from a WAV file. The supported sample formats are 8-bit unsigned integer, 16-bit signed integer, and 32-bit signed integer.

radio.WAVFileSource(file, num_channels[, repeat_on_eof=false])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • num_channels (int): Number of channels (e.g. 1 for mono, 2 for stereo, etc.)
  • repeat_on_eof (bool): Repeat on end of file
Type Signatures
  • ❑➔ out Float32
  • ❑➔ out1 Float32, out2 Float32
Example
-- Source one channel WAV file
local src = radio.WAVFileSource('test.wav', 1)

-- Source two channel WAV file
local src = radio.WAVFileSource('test.wav', 2)
-- Compose the two channels into a complex-valued signal
top:connect(src, 'out1', floattocomplex, 'real')
top:connect(src, 'out2', floattocomplex, 'imag')
top:connect(floattocomplex, ..., snk)

ZeroSource

Source a zero-valued signal of the specified data type.

radio.ZeroSource(data_type, rate)
Arguments
  • data_type (type): LuaRadio data type
  • rate (number): Sample rate in Hz
Type Signatures
  • ❑➔ out data_type
Example
-- Source a zero complex-valued signal sampled at 1 MHz
local src = radio.ZeroSource(radio.types.ComplexFloat32, 1e6)

-- Source a zero real-valued signal sampled at 500 kHz
local src = radio.ZeroSource(radio.types.Bit, 500e3)

-- Source a zero bit stream sampled at 2 kHz
local src = radio.ZeroSource(radio.types.Bit, 2e3)

Sinks

BenchmarkSink

Report the average rate of samples delivered to the sink.

[BenchmarkSink] 314.38 MS/s (2.52 GB/s)
[BenchmarkSink] 313.32 MS/s (2.51 GB/s)
[BenchmarkSink] 313.83 MS/s (2.51 GB/s)
...
radio.BenchmarkSink([file=io.stderr, use_json=false])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • use_json (bool): Serialize aggregate results in JSON on termination
Type Signatures
  • in any ➔❑
Example
-- Benchmark a source, writing periodic results to stderr
local snk = radio.BenchmarkSink()
top:connect(src, snk)

-- Benchmark a source and a block, writing final results in JSON to fd 3
local snk = radio.BenchmarkSink(3, true)
top:connect(src, blk, snk)

GnuplotPlotSink

Plot a real-valued signal in a gnuplot time plot. This sink requires the gnuplot program. This sink should be used with relatively low sample rates, as it does not skip any samples, or it may otherwise throttle a flow graph.

radio.GnuplotPlotSink(num_samples[, title="", options={}])
Arguments
  • num_samples (int): Number of samples to plot
  • title (string): Title of plot
  • options (table): Additional options, specifying:
    • xlabel (string, default “Sample Number”)
    • ylabel (string, default “Value”)
    • yrange (array of two numbers, default nil for autoscale)
    • extra_settings (array of strings containing gnuplot commands)
Type Signatures
  • in Float32 ➔❑
Example
-- Plot a 1 kHz cosine sampled at 250 kHz
local snk = radio.SignalSource('cosine', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotPlotSink(1000, 'Cosine')
top:connect(src, throttle, snk)

GnuplotSpectrumSink

Plot the power spectrum of a complex or real-valued signal. This sink requires the gnuplot program. The power spectral density is estimated with Bartlett’s or Welch’s method of averaging periodograms.

radio.GnuplotSpectrumSink([num_samples=1024, title="", options={}])
Arguments
  • num_samples (int): Number of samples in periodogram
  • title (string): Title of plot
  • options (table): Additional options, specifying:
    • update_time (number, default 0.10 seconds)
    • overlap fraction (number from 0.0 to 1.0, default 0.0)
    • reference_level (number, default 0.0 dB)
    • window (string, default “hamming”)
    • onesided (bool, default true)
    • xrange (array of two numbers, default nil for autoscale)
    • yrange (array of two numbers, default nil for autoscale)
    • extra_settings (array of strings containing gnuplot commands)
Type Signatures
  • in ComplexFloat32 ➔❑
  • in Float32 ➔❑
Example
-- Plot the spectrum of a 1 kHz complex exponential sampled at 250 kHz
local src = radio.SignalSource('exponential', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotSpectrumSink()
top:connect(src, throttle, snk)

GnuplotWaterfallSink

Plot the vertical power spectrogram (waterfall) of a complex or real-valued signal. This sink requires the gnuplot program. The power spectral density is estimated with Bartlett’s or Welch’s method of averaging periodograms.

Note: this sink’s performance is currently limited and should only be used with very low sample rates, or it may otherwise throttle a flow graph.

radio.GnuplotWaterfallSink([num_samples=1024, title="", options={}])
Arguments
  • num_samples (int): Number of samples in periodogram
  • title (string): Title of plot
  • options (table): Additional options, specifying:
    • update_time (number, default 0.10 seconds)
    • overlap fraction (number from 0.0 to 1.0, default 0.0)
    • height in rows (number, default 64)
    • min_magnitude (number, default -150.0 dB)
    • max_magnitude (number, default 0.0 dB)
    • window (string, default “hamming”)
    • onesided (boolean, default true)
    • xrange (array of two numbers, default nil for autoscale)
    • yrange (array of two numbers, default nil for autoscale)
    • extra_settings (array of strings containing gnuplot commands)
Type Signatures
  • in ComplexFloat32 ➔❑
  • in Float32 ➔❑
Example
-- Plot the waterfall of a 1 kHz complex exponential sampled at 250 kHz
local snk = radio.SignalSource('exponential', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotSpectrumSink()
top:connect(src, throttle, snk)

GnuplotXYPlotSink

Plot two real-valued signals, or the real and imaginary components of one complex-valued signal, in a gnuplot XY plot. This sink requires the gnuplot program. This sink should be used with relatively low sample rates, as it does not skip any samples, or it may otherwise throttle a flow graph.

radio.GnuplotXYPlotSink(num_samples[, title="", options={}])
Arguments
  • num_samples (int): Number of samples to plot
  • title (string): Title of plot
  • options (table): Additional options, specifying:
    • complex (bool, default false)
    • xlabel (string, default “”)
    • ylabel (string, default “”)
    • xrange (array of two numbers, default nil for autoscale)
    • yrange (array of two numbers, default nil for autoscale)
    • extra_settings (array of strings containing gnuplot commands)
Type Signatures
  • x Float32, y Float32 ➔❑
  • in ComplexFloat32 ➔❑
Example
-- Plot a 1 kHz complex exponential sampled at 250 kHz
local snk = radio.SignalSource('exponential', 1e3, 250e3)
local throttle = radio.ThrottleBlock()
local snk = radio.GnuplotXYPlotSink(1000, 'Complex Exponential', {complex = true})
top:connect(src, throttle, snk)

-- Plot two real-valued signals
local snk = radio.GnuplotXYPlotSink(1000, 'XY')
top:connect(src1, 'out', snk, 'x')
top:connect(src2, 'out', snk, 'y')

HackRFSink

Sink a complex-valued signal to a HackRF One. This sink requires the libhackrf library.

radio.HackRFSink(frequency[, options={}])
Arguments
  • frequency (number): Tuning frequency in Hz
  • options (table): Additional options, specifying:
    • vga_gain (int in dB, default 0 dB, range 0 to 47 dB, 1 dB step)
    • bandwidth (number in Hz, default round down from sample rate)
    • rf_amplifier_enable (bool, default false)
    • antenna_power_enable (bool, default false)
Type Signatures
  • in ComplexFloat32 ➔❑
Example
-- Sink samples to 146 MHz
local snk = radio.HackRFSink(146e6)

-- Sink samples to 433.92 MHz, with 1.75 MHz baseband bandwidth
local src = radio.HackRFSink(433.92e6, {bandwidth = 1.75e6})

-- Sink samples to 915 MHz, with 22 dB VGA gain
local src = radio.HackRFSink(915e6, {vga_gain = 22})

-- Sink samples to 144.390 MHz, with antenna power enabled
local src = radio.HackRFSink(144.390e6, {antenna_power_enable = true})

IQFileSink

Sink a complex-valued signal to a binary “IQ” file. The file format may be 8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big endianness, and will be interleaved as real component followed by imaginary component.

radio.IQFileSink(file, format)
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • format (string): File format specifying signedness, bit width, and endianness of samples. Choice of “s8”, “u8”, “u16le”, “u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”, “f32le”, “f32be”, “f64le”, “f64be”.
Type Signatures
  • in ComplexFloat32 ➔❑
Example
-- Sink signed 8-bit IQ samples to a file
local snk = radio.IQFileSink('samples.s8.iq', 's8')

-- Sink little-endian 32-bit IQ samples to a file
local snk = radio.IQFileSink('samples.f32le.iq', 'f32le')

-- Sink little-endian signed 16-bit IQ samples to stdout
local snk = radio.IQFileSink(1, 's16le')

JSONSink

Sink a signal to a file, serialized in JSON. Samples are serialized individually and newline delimited. This sink accepts any data type that implements to_json().

radio.JSONSink([file=io.stdout])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
Type Signatures
  • in supported ➔❑
Example
-- Sink JSON serialized samples to stdout
local snk = radio.JSONSink()
top:connect(src, snk)

-- Sink JSON serialized samples to a file
local snk = radio.JSONSink('out.json')
top:connect(src, snk)

NopSink

Sink a signal and do nothing. This sink accepts any data type.

radio.NopSink()
Type Signatures
  • in any ➔❑
Example
local snk = radio.NopSink()
top:connect(src, snk)

PortAudioSink

Sink one or more real-valued signals to the system’s audio device with PortAudio. This sink requires the PortAudio library.

radio.PortAudioSink(num_channels)
Arguments
  • num_channels (int): Number of channels (e.g. 1 for mono, 2 for stereo)
Type Signatures
  • in Float32 ➔❑
  • in1 Float32, in2 Float32 ➔❑
Example
-- Sink to one channel (mono) audio
local snk = radio.PortAudioSink(1)
top:connect(src, snk)

-- Sink to two channel (stereo) audio
local snk = radio.PortAudioSink(2)
top:connect(src_left, 'out', snk, 'in1')
top:connect(src_right, 'out', snk, 'in2')

PrintSink

Sink a signal to a file, formatted as a string. Samples are formatted individually and newline delimited. This sink accepts any data type that implements __tostring().

radio.PrintSink([file=io.stdout])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
Type Signatures
  • in supported ➔❑
Example
-- Sink string formatted samples to stdout
local snk = radio.PrintSink()
top:connect(src, snk)

PulseAudioSink

Sink one or more real-valued signals to the system’s audio device with PulseAudio. This sink requires PulseAudio.

radio.PulseAudioSink(num_channels)
Arguments
  • num_channels (int): Number of channels (e.g. 1 for mono, 2 for stereo)
Type Signatures
  • in Float32 ➔❑
  • in1 Float32, in2 Float32 ➔❑
Example
-- Sink to one channel (mono) audio
local snk = radio.PulseAudioSink(1)
top:connect(src, snk)

-- Sink to two channel (stereo) audio
local snk = radio.PulseAudioSink(2)
top:connect(src_left, 'out', snk, 'in1')
top:connect(src_right, 'out', snk, 'in2')

RawFileSink

Sink a signal to a binary file. The samples are serialized raw, in their native binary representation, with no signedness conversion, endian conversion, or interpretation. This is useful for serializing data types across a pipe or other file descriptor based IPC.

radio.RawFileSink(file)
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
Type Signatures
  • in any ➔❑
Example
-- Sink raw samples to a file
local snk = radio.RawFileSink('samples.raw')
top:connect(src, snk)

-- Sink raw samples to file descriptor 3
local snk = radio.RawFileSink(3)
top:connect(src, snk)

RealFileSink

Sink a real-valued signal to a binary file. The file format may be 8/16/32-bit signed/unsigned integers or 32/64-bit floats, in little or big endianness. This is the real-valued counterpart of IQFileSink.

radio.RealFileSink(file, format)
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • format (string): File format specifying signedness, bit width, and endianness of samples. Choice of “s8”, “u8”, “u16le”, “u16be”, “s16le”, “s16be”, “u32le”, “u32be”, “s32le”, “s32be”, “f32le”, “f32be”, “f64le”, “f64be”.
Type Signatures
  • in Float32 ➔❑
Example
-- Sink signed 8-bit real samples to a file
local snk = radio.RealFileSink('samples.s8.real', 's8')

-- Sink little-endian 32-bit real samples to a file
local snk = radio.RealFileSink('samples.f32le.real', 'f32le', 1e6, true)

-- Sink little-endian signed 16-bit real samples to stdout
local snk = radio.RealFileSink(1, 's16le')

SoapySDRSink

Sink a complex-valued signal to a SoapySDR device. This sink requires SoapySDR.

radio.SoapySDRSink(driver, frequency[, options={}])
Arguments
  • driver (string|table): Driver string or key-value table
  • frequency (number): Tuning frequency in Hz
  • options (table): Additional options, specifying:
    • channel (int, default 0)
    • bandwidth (number in Hz)
    • autogain (bool)
    • antenna (string)
    • gain (number in dB, overall gain)
    • gains (table, gain element name to value in dB)
    • frequencies (table, frequency element name to value in Hz)
    • settings (table, string key-value pairs of driver-specific settings)
Type Signatures
  • in ComplexFloat32 ➔❑
Example
-- Sink samples to a HackRF at 433.92 MHz
local src = radio.SoapySDRSink("driver=hackrf", 433.92e6)

-- Sink samples to a LimeSDR at 915 MHz, with 10 dB overall gain and 5 MHz baseband bandwidth
local src = radio.SoapySDRSink("driver=limesdr", 915e6, {gain = 10, bandwidth = 5e6})

UHDSink

Sink a complex-valued signal to a USRP. This source requires the libuhd library.

radio.UHDSink(device_address, frequency[, options={}])
Arguments
  • device_address (string): Device address string
  • frequency (number): Tuning frequency in Hz
  • options (table): Additional options, specifying:
    • channel (int, default 0)
    • gain (number in dB, overall gain, default 0.0 dB)
    • bandwidth (number in Hz)
    • antenna (string)
    • gains (table, gain element name to value in dB)
Type Signatures
  • in ComplexFloat32 ➔❑
Example
-- Sink samples to a B200 at 433.92 MHz
local src = radio.UHDSink("type=b200", 433.92e6)

-- Sink samples to a B200 at 915 MHz, with 10 dB overall gain and 5 MHz baseband bandwidth
local src = radio.UHDSink("type=b200", 915e6, {gain = 10, bandwidth = 5e6})

WAVFileSink

Sink one or more real-valued signals to a WAV file. The supported sample formats are 8-bit unsigned integer, 16-bit signed integer, and 32-bit signed integer.

radio.WAVFileSink(file, num_channels[, bits_per_sample=16])
Arguments
  • file (string|file|int): Filename, file object, or file descriptor
  • num_channels (int): Number of channels (e.g. 1 for mono, 2 for stereo, etc.)
  • bits_per_sample (int): Bits per sample, choice of 8, 16, or 32
Type Signatures
  • in Float32 ➔❑
  • in1 Float32, in2 Float32 ➔❑
Example
-- Sink to a one channel WAV file
local snk = radio.WAVFileSink('test.wav', 1)
top:connect(src, snk)

-- Sink to a two channel WAV file
local snk = radio.WAVFileSink('test.wav', 2)
top:connect(src1, 'out', snk, 'in1')
top:connect(src2, 'out', snk, 'in2')

Filtering

BandpassFilterBlock

Filter a complex or real valued signal with a real-valued FIR band-pass filter generated by the window design method.

radio.BandpassFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
Arguments
  • num_taps (int): Number of FIR taps, must be odd
  • cutoffs ({number,number}): Cutoff frequencies in Hz
  • nyquist (number): Nyquist frequency, if specifying normalized cutoff frequencies
  • window (string): Window type
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Bandpass filter, 128 taps, 18 kHz to 20 kHz
local bpf = radio.BandpassFilterBlock(128, {18e3, 20e3})

BandstopFilterBlock

Filter a complex or real valued signal with a real-valued FIR band-stop filter generated by the window design method.

radio.BandstopFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
Arguments
  • num_taps (int): Number of FIR taps, must be odd
  • cutoffs ({number,number}): Cutoff frequencies in Hz
  • nyquist (number): Nyquist frequency, if specifying normalized cutoff frequencies
  • window (string): Window type
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Bandstop filter, 128 taps, 18 kHz to 20 kHz
local bpf = radio.BandstopFilterBlock(128, {18e3, 20e3})

ComplexBandpassFilterBlock

Filter a complex-valued signal with a complex-valued FIR band-pass filter generated by the window design method. This filter is asymmetric in the frequency domain.

radio.ComplexBandpassFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
Arguments
  • num_taps (int): Number of FIR taps, must be odd
  • cutoffs ({number,number}): Cutoff frequencies in Hz
  • nyquist (number): Nyquist frequency, if specifying normalized cutoff frequencies
  • window (string): Window type
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Complex bandpass filter, 128 taps, 18 kHz to 20 kHz
local bpf1 = radio.BandpassFilterBlock(128, {18e3, 20e3})

-- Complex bandpass filter, 128 taps, -18 kHz to -20 kHz
local bpf2 = radio.BandpassFilterBlock(128, {-18e3, -20e3})

ComplexBandstopFilterBlock

Filter a complex-valued signal with a complex-valued FIR band-stop filter generated by the window design method. This filter is asymmetric in the frequency domain.

radio.ComplexBandstopFilterBlock(num_taps, cutoffs[, nyquist=nil, window='hamming'])
Arguments
  • num_taps (int): Number of FIR taps, must be odd
  • cutoffs ({number,number}): Cutoff frequencies in Hz
  • nyquist (number): Nyquist frequency, if specifying normalized cutoff frequencies
  • window (string): Window type
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Complex bandstop filter, 128 taps, 18 kHz to 20 kHz
local bpf1 = radio.BandstopFilterBlock(128, {18e3, 20e3})

-- Complex bandstop filter, 128 taps, -18 kHz to -20 kHz
local bpf2 = radio.BandstopFilterBlock(128, {-18e3, -20e3})

FIRFilterBlock

Filter a complex or real valued signal with an FIR filter.

radio.FIRFilterBlock(taps[, use_fft])
Arguments
  • taps (array|vector): Real-valued taps specified with a number array or a Float32 vector, or complex-valued taps specified with a ComplexFloat32 vector
  • use_fft (bool): Use FFT overlap-save convolution. Defaults to true when acceleration is available and taps length is greater than 16
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Moving average FIR filter with 5 real taps
local filter = radio.FIRFilterBlock({1/5, 1/5, 1/5, 1/5, 1/5})

-- Moving average FIR filter with 5 real taps
local taps = radio.types.Float32.vector({1/5, 1/5, 1/5, 1/5, 1/5})
local filter = radio.FIRFilterBlock(taps)

-- FIR filter with 3 complex taps
local taps = radio.types.ComplexFloat32.vector({{1, 1}, {0.5, 0.5}, {0.25, 0.25}})
local filter = radio.FIRFilterBlock(taps)

FMDeemphasisFilterBlock

Filter a complex or real valued signal with an FM De-emphasis filter, a single-pole low-pass IIR filter.

radio.FMDeemphasisFilterBlock(tau)
Arguments
  • tau (number): Time constant of filter
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- FM de-emphasis filter with 75uS time constant for the Americas
local fmdeemph = radio.FMDeemphasisFilterBlock(75e-6)

FMPreemphasisFilterBlock

Filter a complex or real valued signal with an FM Pre-emphasis filter, a single-pole high-pass IIR filter.

radio.FMPreemphasisFilterBlock(tau)
Arguments
  • tau (number): Time constant of filter
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- FM pre-emphasis filter with 75uS time constant for the Americas
local fmpreemph = radio.FMPreemphasisFilterBlock(75e-6)

HighpassFilterBlock

Filter a complex or real valued signal with a real-valued FIR high-pass filter generated by the window design method.

radio.HighpassFilterBlock(num_taps, cutoff[, nyquist=nil, window='hamming'])
Arguments
  • num_taps (int): Number of FIR taps, must be odd
  • cutoff (number): Cutoff frequency in Hz
  • nyquist (number): Nyquist frequency, if specifying a normalized cutoff frequency
  • window (string): Window type
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Highpass filter, 128 taps, 18 kHz
local hpf = radio.HighpassFilterBlock(128, 18e3)

IIRFilterBlock

Filter a complex or real valued signal with an IIR filter.

radio.IIRFilterBlock(b_taps, a_taps)
Arguments
  • b_taps (array|vector): Real-valued feedforward taps specified with a number array or a Float32 vector
  • a_taps (array|vector): Real-valued feedback taps specified with a number array or a Float32 vector, must be at least length 1
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- 2nd order Butterworth IIR filter, Wn=0.1
local filter = radio.IIRFilterBlock({0.02008337,  0.04016673,  0.02008337},
                                    {1, -1.56101808,  0.64135154})

-- 2nd order Butterworth IIR filter, Wn=0.1
local b_taps = radio.types.Float32.vector_from_array({0.02008337,  0.04016673,  0.02008337})
local a_taps = radio.types.Float32.vector_from_array({1, -1.56101808,  0.64135154})
local filter = radio.IIRFilterBlock(b_taps, a_taps)

LowpassFilterBlock

Filter a complex or real valued signal with a real-valued FIR low-pass filter generated by the window design method.

radio.LowpassFilterBlock(num_taps, cutoff[, nyquist=nil, window='hamming'])
Arguments
  • num_taps (int): Number of FIR taps
  • cutoff (number): Cutoff frequency in Hz
  • nyquist (number): Nyquist frequency, if specifying a normalized cutoff frequency
  • window (string): Window type
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Lowpass filter, 128 taps, 18 kHz
local lpf = radio.LowpassFilterBlock(128, 18e3)

RootRaisedCosineFilterBlock

Filter a complex or real valued signal with an FIR approximation of a root raised cosine filter.

radio.RootRaisedCosineFilterBlock(num_taps, beta, symbol_rate)
Arguments
  • num_taps (int): Number of FIR taps, must be odd
  • beta (number): Roll-off factor
  • symbol_rate (number): Symbol rate in Hz
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Root raised cosine filter with 101 taps, 1.0 beta, 1187.5 symbol rate
local rrcfilter = radio.RootRaisedCosineFilterBlock(101, 1.0, 1187.5)

SinglepoleHighpassFilterBlock

Filter a complex or real valued signal with a single-pole high-pass IIR filter.

radio.SinglepoleHighpassFilterBlock(cutoff)
Arguments
  • cutoff (number): Cutoff frequency in Hz
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Single-pole highpass filter with 100 Hz cutoff
local hpf = radio.SinglepoleHighpassFilterBlock(100)

SinglepoleLowpassFilterBlock

Filter a complex or real valued signal with a single-pole low-pass IIR filter.

radio.SinglepoleLowpassFilterBlock(cutoff)
Arguments
  • cutoff (number): Cutoff frequency in Hz
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Single-pole lowpass filter with 100 kHz cutoff
local lpf = radio.SinglepoleLowpassFilterBlock(100e3)

Math Operations

AbsoluteValueBlock

Compute the absolute value of a real-valued signal.

radio.AbsoluteValueBlock()
Type Signatures
  • in Float32 ➔❑➔ out Float32
Example
local abs = radio.AbsoluteValueBlock()

AddBlock

Add two complex or real valued signals.

radio.AddBlock()
Type Signatures
  • in1 ComplexFloat32, in2 ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in1 Float32, in2 Float32 ➔❑➔ out Float32
Example
local summer = radio.AddBlock()
top:connect(src1, 'out', summer, 'in1')
top:connect(src2, 'out', summer, 'in2')
top:connect(summer, snk)

AddConstantBlock

Add a real-valued constant to a complex or real valued signal, or a complex-valued constant to a complex-valued signal.

radio.AddConstantBlock(constant)
Arguments
  • constant (number|Float32|ComplexFloat32): Constant
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Add a number (Float32) constant
local addconstant = radio.AddConstantBlock(1.0)

-- Add a Float32 constant
local addconstant = radio.AddConstantBlock(radio.types.Float32(1.0))

-- Add a ComplexFloat32 constant
local addconstant = radio.AddConstantBlock(radio.types.ComplexFloat32(1.0))

ComplexConjugateBlock

Compute the complex conjugate of a complex-valued signal.

radio.ComplexConjugateBlock()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
local conj = radio.ComplexConjugateBlock()

ComplexMagnitudeBlock

Compute the magnitude of a complex-valued signal.

radio.ComplexMagnitudeBlock()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
local magnitude = radio.ComplexMagnitudeBlock()

ComplexPhaseBlock

Compute the argument (phase) of a complex-valued signal.

radio.ComplexPhaseBlock()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
local phase = radio.ComplexPhaseBlock()

MultiplyBlock

Multiply two complex or real valued signals.

radio.MultiplyBlock()
Type Signatures
  • in1 ComplexFloat32, in2 ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in1 Float32, in2 Float32 ➔❑➔ out Float32
Example
local multiplier = radio.MultipyBlock()
top:connect(src1, 'out', multiplier, 'in1')
top:connect(src2, 'out', multiplier, 'in2')
top:connect(multiplier, snk)

MultiplyConjugateBlock

Multiply a complex-valued signal by the complex conjugate of another complex-valued signal.

radio.MultiplyConjugateBlock()
Type Signatures
  • in1 ComplexFloat32, in2 ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
local multiplier = radio.MultipyConjugateBlock()
top:connect(src1, 'out', multiplier, 'in1')
top:connect(src2, 'out', multiplier, 'in2')
top:connect(multiplier, snk)

MultiplyConstantBlock

Multiply a complex or real valued signal by a real-valued constant, or multiply a complex-valued signal by a complex-valued constant.

radio.MultiplyConstantBlock(constant)
Arguments
  • constant (number|Float32|ComplexFloat32): Constant
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Multiply by number (Float32) constant
local gain = radio.MultiplyConstantBlock(5.0)

-- Multiply by Float32 constant
local gain = radio.MultiplyConstantBlock(radio.types.Float32(5.0))

-- Complex rotation by 45 degrees
local rotator = radio.MultiplyConstantBlock(radio.types.ComplexFloat32(math.cos(math.pi/4),
                                                                       math.sin(math.pi/4)))

SubtractBlock

Subtract two complex or real valued signals.

radio.SubtractBlock()
Type Signatures
  • in1 ComplexFloat32, in2 ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in1 Float32, in2 Float32 ➔❑➔ out Float32
Example
local subtractor = radio.SubtractBlock()
top:connect(src1, 'out', subtractor, 'in1')
top:connect(src2, 'out', subtractor, 'in2')
top:connect(subtractor, snk)

Level Control

AGCBlock

Apply automatic gain to a real or complex valued signal to maintain an average target power.

Implementation note: this is a feedforward AGC. The power_tau time constant controls the moving average of the power estimator. The gain_tau time constant controls the speed of the gain adjustment. The gain has symmetric attack and decay dynamics.

radio.AGCBlock(mode[, target=-35, threshold=-75, options={}])
Arguments
  • mode (string): Mode, choice of “fast”, “slow”, “custom”
  • target (number): Target power in dBFS
  • threshold (number): Threshold power in dBFS
  • options (table): Additional options, specifying:
    • gain_tau (number, default 0.1 seconds for fast, 3.0 seconds for slow)
    • power_tau (number, default 1.0 seconds)
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Automatic gain control with fast gain
local agc = radio.AGCBlock('fast')

-- Automatic gain control with slow gain, -20 dbFS target
local agc = radio.AGCBlock('slow', -20)

-- Automatic gain control with custom time constant, -30 dbFS target, -100 dbFS threshold
local agc = radio.AGCBlock('custom', -30, -100, {gain_tau = 0.5})

PowerSquelchBlock

Squelch a real or complex valued signal by its average power.

radio.PowerSquelchBlock(threshold[, tau=0.001])
Arguments
  • threshold (number): Power threshold in dBFS
  • tau (number): Time constant of moving average filter in seconds
Type Signatures
  • in Float32 ➔❑➔ out Float32
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Squelch at -40 dBFS power
local squelch = radio.PowerSquelchBlock(-40)

Sample Rate Manipulation

DownsamplerBlock

Downsample a complex or real valued signal. This block reduces the sample rate for downstream blocks in the flow graph by a factor of M.

Note: this block performs no anti-alias filtering. Use the DecimatorBlock for signal decimation with anti-alias filtering.

radio.DownsamplerBlock(factor)
Arguments
  • factor (int): Downsampling factor M
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Downsample by 5
local downsampler = radio.DownsamplerBlock(5)

UpsamplerBlock

Upsample a complex or real valued signal. This block increases the sample rate for downstream blocks in the flow graph by a factor of L.

Note: this block performs no scaling or anti-alias filtering. Use the InterpolatorBlock for signal interpolation with scaling and anti-alias filtering.

radio.UpsamplerBlock(factor)
Arguments
  • factor (int): Upsampling factor L
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Upsample by 5
local upsampler = radio.UpsamplerBlock(5)

DecimatorBlock

Decimate a complex or real valued signal. This block band-limits and downsamples the input signal. It reduces the sample rate for downstream blocks in the flow graph by a factor of M.

radio.DecimatorBlock(decimation[, options={}])
Arguments
  • decimation (int): Downsampling factor M
  • options (table): Additional options, specifying:
    • num_taps (int, default 128)
    • window (string, default “hamming”)
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Decimate by 5
local decimator = radio.DecimatorBlock(5)

InterpolatorBlock

Interpolate a complex or real valued signal. This block scales, band-limits, and upsamples the input signal. It increases the sample rate for downstream blocks in the flow graph by a factor of L.

radio.InterpolatorBlock(interpolation[, options={}])
Arguments
  • interpolation (int): Upsampling factor L
  • options (table): Additional options, specifying:
    • num_taps (int, default 128)
    • window (string, default “hamming”)
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Interpolate by 5
local interpolator = radio.InterpolatorBlock(5)

RationalResamplerBlock

Resample a complex or real valued signal by a rational factor. This block band-limits and resamples the input signal. It changes the sample rate for downstream blocks in the flow graph by a factor of L/M.

radio.RationalResamplerBlock(interpolation, decimation[, options={}])
Arguments
  • interpolation (int): Upsampling factor L
  • decimation (int): Downsampling factor M
  • options (table): Additional options, specifying:
    • num_taps (int, default 128)
    • window (string, default “hamming”)
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
Example
-- Resample by 5/3
local resampler = radio.RationalResamplerBlock(5, 3)

Spectrum Manipulation

FrequencyTranslatorBlock

Frequency translate a complex-valued signal by mixing it with , where .

radio.FrequencyTranslatorBlock(offset)
Arguments
  • offset (number): Translation offset in Hz
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Frequency translate -200 kHz
local translator = radio.FrequencyTranslatorBlock(-200e3)

HilbertTransformBlock

Hilbert transform a real-valued signal into a complex-valued signal with a windowed FIR approximation of the IIR Hilbert transform filter.

radio.HilbertTransformBlock(num_taps[, window='hamming'])
Arguments
  • num_taps (number): Number of FIR taps, must be odd
  • window (string): Window type
Type Signatures
  • in Float32 ➔❑➔ out ComplexFloat32
Example
-- Hilbert transform with 129 taps
local ht = radio.HilbertTransformBlock(129)

TunerBlock

Frequency translate, low-pass filter, and decimate a complex-valued signal. This block reduces the sample rate for downstream blocks in the flow graph by a factor of M.

This block is convenient for translating signals to baseband and decimating them.

radio.TunerBlock(offset, bandwidth, decimation[, options={}])
Arguments
  • offset (number): Translation offset in Hz
  • bandwidth (number): Signal bandwidth in Hz
  • decimation (int): Downsampling factor M
  • options (table): Additional options, specifying:
    • num_taps (int, default 128)
    • window (string, default “hamming”)
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Translate -100 kHz, filter 12 kHz, and decimate by 5
local tuner = radio.TunerBlock(-100e3, 12e3, 5)

Carrier and Clock Recovery

PLLBlock

Generate a phase-locked complex-valued sinusoid to a complex-valued reference signal.

radio.PLLBlock(loop_bandwidth, frequency_min, frequency_max[, multiplier=1.0])
Arguments
  • loop_bandwidth (number): Loop bandwidth in Hz
  • frequency_min (number): Minimum frequency in Hz
  • frequency_max (number): Maximum frequency in Hz
  • multiplier (number): Multiplier, can be fractional
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32, error Float32
Example
-- PLL with 1 kHz loop bandwidth, 18 kHz - 21 kHz capture range, 3 multiplier
local pll = radio.PLLBlock(1e3, 18e3, 21e3, 3)

-- PLL with 1 kHz loop bandwidth, 18 kHz - 21 kHz capture range, 1/16 multiplier
local pll = radio.PLLBlock(1e3, 18e3, 21e3, 1/16)

ZeroCrossingClockRecoveryBlock

Generate a real-valued clock signal from zero-crossings in a data signal. This clock signal can then be used to sample the data signal with a SamplerBlock.

radio.ZeroCrossingClockRecoveryBlock(baudrate[, threshold=0.0])
Arguments
  • baudrate (number): Baudrate in symbols per second
  • threshold (number): Zero-crossing threshold
Type Signatures
  • in Float32 ➔❑➔ out Float32
Example
-- Zero-crossing clock recovery of 1200 baudrate data signal
local clock_recoverer = radio.ZeroCrossingClockRecoveryBlock(1200)
top:connect(src, clock_recoverer)
top:connect(src, 'out', sampler, 'data')
top:connect(clock_recoverer, 'out', sampler, 'clock')
top:connect(sampler, snk)

Digital

BinaryPhaseCorrectorBlock

Correct the phase of a complex-valued BPSK modulated signal, by rotating it against a moving average of the phase angle.

radio.BinaryPhaseCorrectorBlock(num_samples[, sample_interval=32])
Arguments
  • num_samples (int): Number of samples in phase angle moving average
  • sample_interval (int): Number of samples to skip between phase measurements
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Binary phase corrector with a 3000 sample moving average
local phase_corrector = radio.BinaryPhaseCorrector(3000)

DifferentialDecoderBlock

Decode a differentially encoded bit stream.

radio.DifferentialDecoderBlock([invert=false])
Arguments
  • invert (bool): Invert the output.
Type Signatures
  • in Bit ➔❑➔ out Bit
Example
local diff_decoder = radio.DifferentialDecoderBlock()

ManchesterDecoderBlock

Decode a Manchester encoded bit stream.

radio.ManchesterDecoderBlock([invert=false])
Arguments
  • invert (bool): Invert the output.
Type Signatures
  • in Bit ➔❑➔ out Bit
Example
local manchester_decoder = radio.ManchesterDecoderBlock()

SamplerBlock

Sample a complex or real valued data signal on positive zero-crossing transitions of a real-valued clock signal.

radio.SamplerBlock()
Type Signatures
  • data ComplexFloat32, clock Float32 ➔❑➔ out ComplexFloat32
  • data Float32, clock Float32 ➔❑➔ out Float32
Example
local sampler = radio.SamplerBlock()
top:connect(data_src, 'out', sampler, 'data')
top:connect(clock_src, 'out', sampler, 'clock')
top:connect(sampler, snk)

SlicerBlock

Slice a real-valued signal on a threshold into a bit stream.

radio.SlicerBlock([threshold=0.0])
Arguments
  • threshold (number): Threshold
Type Signatures
  • in Float32 ➔❑➔ out Bit
Example
-- Slice at default threshold 0.0
local slicer = radio.SlicerBlock()

-- Slice at threshold 0.5
local slicer = radio.SlicerBlock(0.5)

Type Conversion

ComplexToFloatBlock

Decompose the real and imaginary parts of a complex-valued signal.

radio.ComplexToFloatBlock()
Type Signatures
  • in ComplexFloat32 ➔❑➔ real Float32, imag Float32
Example
local complextofloat = radio.ComplexToFloatBlock()

ComplexToImagBlock

Decompose the imaginary part of a complex-valued signal.

radio.ComplexToImagBlock()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
local complextoimag = radio.ComplexToImagBlock()

ComplexToRealBlock

Decompose the real part of a complex-valued signal.

radio.ComplexToRealBlock()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
local complextoreal = radio.ComplexToRealBlock()

FloatToComplexBlock

Compose two real-valued signals into the real and imaginary parts of a complex-valued signal.

radio.FloatToComplexBlock()
Type Signatures
  • real Float32, imag Float32 ➔❑➔ out ComplexFloat32
Example
local floattocomplex = radio.FloatToComplexBlock()

RealToComplexBlock

Compose a complex-valued signal from a real-valued signal and a zero-valued imaginary part.

radio.RealToComplexBlock()
Type Signatures
  • in Float32 ➔❑➔ out ComplexFloat32
Example
local realtocomplex = radio.RealToComplexBlock()

Miscellaneous

DeinterleaveBlock

Deinterleave a complex or real valued signal.

radio.DeinterleaveBlock([num_channels=2])
Arguments
  • num_channels (int): Number of channels
Type Signatures
  • in Float32 ➔❑➔ out1 Float32, out2 Float32
  • in ComplexFloat32 ➔❑➔ out1 ComplexFloat32, out2 ComplexFloat32
Example
-- Deinterleave two channels
local deinterleaver = radio.DeinterleaveBlock()

-- Deinterleave four channels
local deinterleaver = radio.DeinterleaveBlock(4)

DelayBlock

Delay a signal by a fixed number of samples.

radio.DelayBlock(num_samples)
Arguments
  • num_samples (int): Number of samples to delay
Type Signatures
  • in ComplexFloat32 ➔❑➔ out ComplexFloat32
  • in Float32 ➔❑➔ out Float32
  • in Byte ➔❑➔ out Byte
  • in Bit ➔❑➔ out Bit
Example
-- Delay by 128 samples
local delay = radio.DelayBlock(128)

InterleaveBlock

Interleave a complex or real valued signal.

radio.InterleaveBlock([num_channels=2])
Arguments
  • num_channels (int): Number of channels
Type Signatures
  • in1 Float32, in2 Float32 ➔❑➔ out Float32
  • in1 ComplexFloat32, in2 ComplexFloat32 ➔❑➔ out ComplexFloat32
Example
-- Interleave two channels
local interleaver = radio.InterleaveBlock()

-- Interleave four channels
local interleaver = radio.InterleaveBlock(4)

NopBlock

Pass a signal through, performing no operation.

radio.NopBlock()
Type Signatures
  • in any ➔❑➔ out copy
Example
local nop = radio.NopBlock()
top:connect(src, nop, snk)

ThrottleBlock

Throttle a signal to limit CPU usage and pace plotting sinks.

radio.ThrottleBlock()
Type Signatures
  • in any ➔❑➔ out copy
Example
local throttle = radio.ThrottleBlock()
top:connect(src, throttle, snk)

Modulation

SSBModulator

Modulate a real-valued signal into a baseband, single-sideband amplitude modulated complex-valued signal.

radio.SSBModulator(sideband[, bandwidth=3e3])
Arguments
  • sideband (string): Sideband, choice of “lsb” or “usb”.
  • bandwidth (number): Bandwidth in Hz
Type Signatures
  • in Float32 ➔❑➔ out ComplexFloat32
Example
-- SSB LSB modulator with 3 kHz bandwidth
local mod = radio.SSBModulator("lsb", 3e3)

Demodulation

FrequencyDiscriminatorBlock

Frequency discriminate a complex-valued signal. This is a method of frequency demodulation.

radio.FrequencyDiscriminatorBlock(modulation_index)
Arguments
  • modulation_index (number): Modulation index (Carrier Deviation / Maximum Modulation Frequency)
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
-- Frequency discriminator with modulation index 1.25
local fm_demod = radio.FrequencyDiscriminatorBlock(1.25)

AMEnvelopeDemodulator

Demodulate a baseband, double-sideband amplitude modulated complex-valued signal with an envelope detector.

radio.AMEnvelopeDemodulator([bandwidth=5e3])
Arguments
  • bandwidth (number): Bandwidth in Hz
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
-- AM demodulator with 5 kHz bandwidth
local demod = radio.AMEnvelopeDemodulator(5e3)

AMSynchronousDemodulator

Demodulate a double-sideband amplitude modulated complex-valued signal with a synchronous detector. The input signal should be centered on the specified intermediate frequency.

radio.AMSynchronousDemodulator(ifreq[, bandwidth=5e3])
Arguments
  • ifreq (number): Intermediate frequency in Hz
  • bandwidth (number): Bandwidth in Hz
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
-- AM demodulator with 100 kHz IF, 5 kHz bandwidth
local demod = radio.AMSynchronousDemodulator(100e3, 5e3)

NBFMDemodulator

Demodulate a baseband, narrowband FM modulated complex-valued signal.

The input signal will be band-limited by the specified deviation and bandwidth with a cutoff frequency calculated by Carson’s rule.

radio.NBFMDemodulator([deviation=5e3, bandwidth=4e3])
Arguments
  • deviation (number): Deviation in Hz
  • bandwidth (number): Bandwidth in Hz
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
-- NBFM demodulator with 5 kHz deviation and 4 kHz bandwidth
local demod = radio.NBFMDemodulator(5e3, 4e3)

SSBDemodulator

Demodulate a baseband, single-sideband amplitude modulated complex-valued signal.

radio.SSBDemodulator(sideband[, bandwidth=3e3])
Arguments
  • sideband (string): Sideband, choice of “lsb” or “usb”.
  • bandwidth (number): Bandwidth in Hz
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
-- SSB LSB demodulator with 3 kHz bandwidth
local demod = radio.SSBDemodulator("lsb", 3e3)

WBFMMonoDemodulator

Demodulate a baseband, broadcast radio wideband FM modulated complex-valued signal into the real-valued mono channel (L+R) signal.

radio.WBFMMonoDemodulator([tau=75e-6])
Arguments
  • tau (number): FM de-emphasis time constant
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Float32
Example
local demod = radio.WBFMMonoDemodulator()

WBFMStereoDemodulator

Demodulate a baseband, broadcast radio wideband FM modulated complex-valued signal into the real-valued stereo channel (L and R) signals.

radio.WBFMStereoDemodulator([tau=75e-6])
Arguments
  • tau (number): FM de-emphasis time constant
Type Signatures
  • in ComplexFloat32 ➔❑➔ left Float32, right Float32
Example
local demod = radio.WBFMStereoDemodulator()

Protocol

AX25FramerBlock

Validate and extract AX.25 frames from a bit stream.

radio.AX25FramerBlock()
Type Signatures
  • in Bit ➔❑➔ out AX25FrameType
Example
local framer = radio.AX25FramerBlock()

AX25FramerBlock.AX25FrameType

radio.AX25FramerBlock.AX25FrameType(addresses, control, pid, payload)

AX.25 frame type, a Lua object with properties:

{
  addresses = {
    {
      callsign = <string>,
      ssid = <integer>
    },
    ...
  },
  control = <integer>,
  pid = <integer>,
  payload = <byte string>,
}
Arguments
  • addresses (array): Array of addresses, each a table with key callsign containing a 6-character string callsign and key ssid containing a 7-bit wide integer SSID
  • control (int): Control field, 8-bits wide
  • pid (int): PID field, 8-bits wide
  • payload (string): Payload byte string (variable length)

POCSAGDecoderBlock

Decode POCSAG frames into POCSAG messages. This block decodes alphanumeric strings, numeric strings, or both.

radio.POCSAGDecoderBlock([mode='alphanumeric'])
Arguments
  • mode (string): Decoding mode, choice of “alphanumeric”, “numeric”, or “both”.
Type Signatures
  • in POCSAGFrameType ➔❑➔ out POCSAGMessageType
Example
local decoder = radio.POCSAGDecoderBlock()

POCSAGDecoderBlock.POCSAGMessageType

radio.POCSAGDecoderBlock.POCSAGMessageType(address, func, alphanumeric, numeric)

POCSAG message type, a Lua object with properties:

{
  address = <21-bit integer>,
  func = <2-bit integer>,
  alphanumeric = <string>,
  numeric = <string>,
}
Arguments
  • address (int): Address bits, 21-bits wide
  • func (int): Function bits, 2-bits wide
  • alphanumeric (string): Decoded alphanumeric string
  • numeric (string): Decoded numeric string

POCSAGFramerBlock

Detect, correct, validate, and extract POCSAG frames from a bit stream. Each frame contains a single message with address, function bits, and data, so a POCSAG transmission of several batches may yield several frames.

radio.POCSAGFramerBlock()
Type Signatures
  • in Bit ➔❑➔ out POCSAGFrameType
Example
local framer = radio.POCSAGFramerBlock()

POCSAGFramerBlock.POCSAGFrameType

radio.POCSAGFramerBlock.POCSAGFrameType(address, func, data)

POCSAG frame type, a Lua object with properties:

{
  address = <21-bit integer>,
  func = <2-bit integer>,
  data = {<20-bit integer>, ...},
}
Arguments
  • address (int): Address bits, 21-bits wide
  • func (int): Function bits, 2-bits wide
  • data (array): Array of data words, each 20-bits wide

RDSDecoderBlock

Decode RDS frames into RDS packets with a header and data payload. The supported data payloads are basic tuning, radiotext, and datetime.

radio.RDSDecoderBlock()
Type Signatures
  • in RDSFrameType ➔❑➔ out RDSPacketType
Example
local decoder = radio.RDSDecoderBlock()

RDSDecoderBlock.RDSPacketType

radio.RDSDecoderBlock.RDSPacketType(header, data)

RDS packet type, a Lua object with properties:

{
  header = {
    pi_code = <16-bit integer>
    group_code = <4-bit integer>
    group_version = <1-bit integer>,
    tp_code = <1-bit integer>,
    pty_code = <5-bit integer>,
  },
  data = <payload object>,
}

The payload object can be one of the four below.

Basic tuning data payload:

{
  type = "basictuning",
  ta_code = <1-bit integer>,
  ms_code = <1-bit integer>,
  di_position = <2-bit integer>,
  di_value = <1-bit integer>,
  af_code = {<8-bit integer>, <8-bit integer>} or nil,
  text_address = <2-bit integer>,
  text_data = <string, length 2>,
}

Radio text data payload:

{
  type = "radiotext",
  ab_flag = <1-bit integer>,
  text_address = <4-bit integer>,
  text_data = <string, length 4 or 2>,
}

Datetime data payload:

{
  type = "datetime",
  date = {year = <integer>, month = <integer>, day = <integer>},
  time = {hour = <integer>, minute = <integer>, offset = <integer>},
}

Raw data payload (for unsupported group/version codes):

{
  type = "raw",
  frame = {<16-bit integer>, <16-bit integer>, <16-bit integer>, <16-bit integer>},
}
Arguments
  • header (table): Header table, as outlined above
  • data (table): Data payload table, as outlined above

RDSFramerBlock

Correct, validate, and extract 104-bit RDS data groups from a bit stream into frames.

radio.RDSFramerBlock()
Type Signatures
  • in Bit ➔❑➔ out RDSFrameType
Example
local framer = radio.RDSFramerBlock()

RDSFramerBlock.RDSFrameType

radio.RDSFramerBlock.RDSFrameType(data)

RDS frame type, a C structure defined as:

typedef struct {
    uint16_t blocks[4];
} rds_frame_t;
Arguments
  • data (table): Array of four data words, e.g. {{0x3aab, 0x02c9, 0x0608, 0x6469}}

VaricodeDecoderBlock

Decode a Varicode encoded bit stream into bytes.

radio.VaricodeDecoderBlock()
Type Signatures
  • in Bit ➔❑➔ out Byte
Example
local decoder = radio.VaricodeDecoderBlock()

Receivers

AX25Receiver

Demodulate and decode AX.25 frames from a baseband, narrowband FM, Bell 202 AFSK modulated complex-valued signal.

radio.AX25Receiver()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out AX25FrameType
Example
local receiver = radio.AX25Receiver()
local snk = radio.JSONSink()
top:connect(src, receiver, snk)

BPSK31Receiver

Demodulate and decode bytes from a baseband BPSK31 modulated complex-valued signal.

radio.BPSK31Receiver()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out Byte
Example
local receiver = radio.BPSK31Receiver()
local snk = radio.RawFileSink(io.stdout)
top:connect(src, receiver, snk)

POCSAGReceiver

Demodulate and decode POCSAG messages from a baseband, 4.5 kHz shift FSK modulated complex-valued signal.

radio.POCSAGReceiver()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out POCSAGMessageType
Example
local receiver = radio.POCSAGReceiver()
local snk = radio.JSONSink()
top:connect(src, receiver, snk)

RDSReceiver

Demodulate and decode RDS frames from a baseband, wideband FM broadcast modulated complex-valued signal.

radio.RDSReceiver()
Type Signatures
  • in ComplexFloat32 ➔❑➔ out RDSFrameType
Example
local receiver = radio.RDSReceiver()
local decoder = radio.RDSDecoderBlock()
local snk = radio.JSONSink()
top:connect(src, receiver, decoder, snk)

Infrastructure

Package

LuaRadio package.

radio._VERSION

string: Package version as a string, e.g. “1.0.0”.


radio.version

string: Package version as a string, e.g. “1.0.0”.


radio.version_number

int: Package version as a number, encoded in decimal as xxyyzz, e.g. v1.2.15 would be 10215.


radio.version_info

table: Package version as a table, with keys major, minor, patch and integer values.


radio.types

module: Types module.


radio.block

module: Block module.


radio.debug

module: Debug module.


radio.platform

module: Platform module.


Basic Types

ComplexFloat32

radio.types.ComplexFloat32([real=0.0, imag=0.0])

ComplexFloat32 data type, a C structure defined as:

typedef struct {
    float real;
    float imag;
} complex_float32_t;
Arguments
  • real (float): Initial real part
  • imag (float): Initial imaginary part
ComplexFloat32.vector(num)

Construct a zero-initialized ComplexFloat32 vector.

Arguments
  • num (int): Number of elements in the vector
Returns
  • ComplexFloat32 vector (Vector)
Example
local vec = radio.types.ComplexFloat32.vector(100)
ComplexFloat32.vector_from_array(arr)

Construct a ComplexFloat32 vector initialized from an array.

Arguments
  • arr (array): Array with element initializers
Returns
  • ComplexFloat32 vector (Vector)
Example
local vec = radio.types.ComplexFloat32.vector_from_array({{1.0, 2.0}, {2.0, 3.0}, {3.0, 4.0}})
ComplexFloat32:__add(other)

Add two ComplexFloat32s.

Arguments
  • other (ComplexFloat32): Operand
Returns
  • Result (ComplexFloat32)
ComplexFloat32:__sub(other)

Subtract two ComplexFloat32s.

Arguments
  • other (ComplexFloat32): Operand
Returns
  • Result (ComplexFloat32)
ComplexFloat32:__mul(other)

Multiply two ComplexFloat32s.

Arguments
  • other (ComplexFloat32): Operand
Returns
  • Result (ComplexFloat32)
ComplexFloat32:__div(other)

Divide two ComplexFloat32s.

Arguments
  • other (ComplexFloat32): Operand
Returns
  • Result (ComplexFloat32)
ComplexFloat32:__eq(other)

Compare two ComplexFloat32s for equality.

Arguments
  • other (ComplexFloat32): Other ComplexFloat32
Returns
  • Result (bool)
ComplexFloat32:__lt(other)

Compare two ComplexFloat32s for less than.

Arguments
  • other (ComplexFloat32): Other ComplexFloat32
Returns
  • Result (bool)
ComplexFloat32:__le(other)

Compare two ComplexFloat32s for less than or equal.

Arguments
  • other (ComplexFloat32): Other ComplexFloat32
Returns
  • Result (bool)
ComplexFloat32:scalar_mul(other)

Multiply a ComplexFloat32 by a scalar.

Arguments
  • other (number): Scalar
Returns
  • Result (ComplexFloat32)
ComplexFloat32:scalar_div(other)

Divide a ComplexFloat32 by a scalar.

Arguments
  • other (number): Scalar
Returns
  • Result (ComplexFloat32)
ComplexFloat32:arg()

Compute the complex argument, in interval .

Returns
  • Result (number)
ComplexFloat32:abs()

Compute the complex magnitude.

Returns
  • Result (number)
ComplexFloat32:abs_squared()

Compute the complex magnitude squared.

Returns
  • Result (number)
ComplexFloat32.approx_equal(x, y, epsilon)

Compare two ComplexFloat32s for approximate equality within the specified epsilon.

Arguments
  • x (ComplexFloat32): First ComplexFloat32
  • y (ComplexFloat32): Second ComplexFloat32
  • epsilon (number): Epsilon
Returns
  • Result (bool)
ComplexFloat32:__tostring()

Get a string representation.

Returns
  • String representation (string)
Example
local x = radio.types.ComplexFloat32()
print(x)) --> ComplexFloat32<real=0, imag=0>

Float32

radio.types.Float32([value=0.0])

Float32 data type, a C structure defined as:

typedef struct {
    float value;
} float32_t;
Arguments
  • value (float): Initial value
Float32.vector(num)

Construct a zero-initialized Float32 vector.

Arguments
  • num (int): Number of elements in the vector
Returns
  • Float32 vector (Vector)
Example
local vec = radio.types.Float32.vector(100)
Float32.vector_from_array(arr)

Construct a Float32 vector initialized from an array.

Arguments
  • arr (array): Array with element initializers
Returns
  • Float32 vector (Vector)
Example
local vec = radio.types.Float32.vector_from_array({1.0, 2.0, 3.0})
Float32:__add(other)

Add two Float32s.

Arguments
  • other (Float32): Operand
Returns
  • Result (Float32)
Float32:__sub(other)

Subtract two Float32s.

Arguments
  • other (Float32): Operand
Returns
  • Result (Float32)
Float32:__mul(other)

Multiply two Float32s.

Arguments
  • other (Float32): Operand
Returns
  • Result (Float32)
Float32:__div(other)

Divide two Float32s.

Arguments
  • other (Float32): Operand
Returns
  • Result (Float32)
Float32:__eq(other)

Compare two Float32s for equality.

Arguments
  • other (Float32): Other Float32
Returns
  • Result (bool)
Float32:__lt(other)

Compare two Float32s for less than.

Arguments
  • other (Float32): Other Float32
Returns
  • Result (bool)
Float32:__le(other)

Compare two Float32s for less than or equal.

Arguments
  • other (Float32): Other Float32
Returns
  • Result (bool)
Float32.approx_equal(x, y, epsilon)

Compare two Float32s for approximate equality within the specified epsilon.

Arguments
  • x (Float32): First Float32
  • y (Float32): Second Float32
  • epsilon (number): Epsilon
Returns
  • Result (bool)
Float32:__tostring()

Get a string representation.

Returns
  • String representation (string)
Example
local x = radio.types.Float32()
print(x)) --> Float32<value=0>

Bit

radio.types.Bit([value=0])

Bit data type, a C structure defined as:

typedef struct {
    uint8_t value;
} bit_t;
Arguments
  • value (int): Initial value
Bit.vector(num)

Construct a zero-initialized Bit vector.

Arguments
  • num (int): Number of elements in the vector
Returns
  • Bit vector (Vector)
Example
local vec = radio.types.Bit.vector(100)
Bit.vector_from_array(arr)

Construct a Bit vector initialized from an array.

Arguments
  • arr (array): Array with element initializers
Returns
  • Bit vector (Vector)
Example
local vec = radio.types.Bit.vector_from_array({1, 0, 1, 0, 1, 1, 0})
Bit:band(other)

Bitwise-AND two Bits.

Arguments
  • other (Bit): Operand
Returns
  • Result (Bit)
Bit:bor(other)

Bitwise-OR two Bits.

Arguments
  • other (Bit): Operand
Returns
  • Result (Bit)
Bit:bxor(other)

Bitwise-XOR two Bits.

Arguments
  • other (Bit): Operand
Returns
  • Result (Bit)
Bit:bnot()

Bitwise-NOT a Bit.

Returns
  • Result (Bit)
Bit:__eq(other)

Compare two Bits for equality.

Arguments
  • other (Bit): Other bit
Returns
  • Result (bool)
Bit:__tostring()

Get a string representation.

Returns
  • String representation (string)
Example
local x = radio.types.Bit()
print(x)) --> Bit<value=0>
Bit.tonumber(vec[, offset=0, length=0, order="msb"])

Convert a Bit vector to a number.

Arguments
  • vec (Vector): Bit vector
  • offset (int): Offset
  • length (int): Length
  • order (string): Bit order. Choice of “msb” or “lsb”.
Returns
  • Extracted number (number)
Example
local vec = radio.types.Bit.vector_from_array({0, 1, 0, 1})
assert(radio.types.Bit.tonumber(vec) == 5)
assert(radio.types.Bit.tonumber(vec, 0, 4, 'lsb') == 10)
assert(radio.types.Bit.tonumber(vec, 2, 2, 'msb') == 1)
assert(radio.types.Bit.tonumber(vec, 2, 2, 'lsb') == 2)

Byte

radio.types.Byte([value=0])

Byte data type, a C structure defined as:

typedef struct {
    uint8_t value;
} byte_t;
Arguments
  • value (int): Initial value
Byte.vector(num)

Construct a zero-initialized Byte vector.

Arguments
  • num (int): Number of elements in the vector
Returns
  • Byte vector (Vector)
Example
local vec = radio.types.Byte.vector(100)
Byte.vector_from_array(arr)

Construct a Byte vector initialized from an array.

Arguments
  • arr (array): Array with element initializers
Returns
  • Byte vector (Vector)
Example
local vec = radio.types.Byte.vector_from_array({0xde, 0xad, 0xbe, 0xef})
Byte:__add(other)

Add two Bytes.

Arguments
  • other (Bit): Operand
Returns
  • Result (Byte)
Byte:__sub(other)

Subtract two Bytes.

Arguments
  • other (Bit): Operand
Returns
  • Result (Byte)
Byte:__mul(other)

Multiply two Bytes.

Arguments
  • other (Bit): Operand
Returns
  • Result (Byte)
Byte:__div(other)

Divide two Bytes.

Arguments
  • other (Bit): Operand
Returns
  • Result (Byte)
Byte:__eq(other)

Compare two Bytes for equality.

Arguments
  • other (Bit): Other byte
Returns
  • Result (bool)
Byte:__lt(other)

Compare two Bytes for less than.

Arguments
  • other (Bit): Other byte
Returns
  • Result (bool)
Byte:__le(other)

Compare two Bytes for less than or equal.

Arguments
  • other (Bit): Other byte
Returns
  • Result (bool)
Byte:__tostring()

Get a string representation.

Returns
  • String representation (string)
Example
local x = radio.types.Byte()
print(x)) --> Byte<value=0>

Type Factories

CStructType

radio.types.CStructType()

CStruct data type base class.

CStructType.factory(ctype[, methods={}])

Construct a new data type based on a C structure type. The data type will be serializable between blocks in a flow graph.

Arguments
  • ctype (string|ctype): C type
  • methods (table): Table of methods and metamethods
Returns
  • Data type (class)
CStructType:new(...)

Construct a new instance of this type.

Arguments
  • ...: Arguments
CStructType:vector(num)

Construct a zero-initialized vector of this type.

Arguments
  • num (int): Number of elements in the vector
Returns
  • Vector (Vector)
CStructType:vector_from_array(arr)

Construct a vector of this type initialized from an array.

Arguments
  • arr (array): Array with element initializers
Returns
  • Vector (Vector)
CStructType:__eq(other)

Compare two instances of this type.

Arguments
  • other (CStructType): Other instance
Returns
  • Result (bool)

ObjectType

radio.types.ObjectType()

Object data type base class.

ObjectType.factory([methods={}])

Construct a new data type based on a Lua object. The data type will be serializable between blocks in a flow graph.

The new() constructor must be provided by the implementation.

Arguments
  • methods (table): Table of methods and metamethods
Returns
  • Data type (class)
ObjectType:vector(num)

Construct a vector of this type.

Arguments
  • num (int): Number of elements in the vector
Returns
  • Vector (ObjectVector)
ObjectType:vector_from_array(arr)

Construct a vector of this type initialized from an array.

Arguments
  • arr (array): Array with element initializers
Returns
  • Vector (ObjectVector)
ObjectType:to_msgpack()

Serialize this object with MessagePack.

Returns
  • MessagePack serialized object (string)
ObjectType:to_json()

Serialize this object with JSON.

Returns
  • JSON serialized object (string)
ObjectType:from_msgpack(str)

Deserialize an instance of this type with MessagePack.

Arguments
  • str (string): MessagePack serialized object
Returns
  • Deserialized object (ObjectType)
ObjectType:from_json(str)

Deserialize an instance of this type with JSON.

Arguments
  • str (string): JSON serialized object
Returns
  • Deserialized object (ObjectType)

Vector

Vector classes.

Vector

radio.vector.Vector(ctype[, num=0])

A dynamic array of a C structure type.

Arguments
  • ctype (ctype): C type
  • num (int): Length
Vector:__eq(other)

Compare two vectors for equality.

Arguments
  • other (vector): Other vector
Returns
  • Result (bool)
Vector:__tostring()

Get a string representation.

Returns
  • String representation (string)
Vector:resize(num)

Resize the vector.

Arguments
  • num (int): New length
Returns
  • self (Vector)
Vector:append(elem)

Append an element to the vector.

Arguments
  • elem: Element
Returns
  • self (Vector)

ObjectVector

radio.vector.ObjectVector(type[, num=0])

A dynamic array of a Lua object type.

Arguments
  • type (type): Lua class
  • num (int): Length
ObjectVector:__tostring()

Get a string representation.

Returns
  • String representation (string)
ObjectVector:resize(num)

Resize the vector.

Arguments
  • num (int): New length
Returns
  • self (Vector)
ObjectVector:append(elem)

Append an element to the vector.

Arguments
  • elem: Element
Returns
  • self (Vector)

Block

Support classes for creating blocks.

Input

radio.block.Input(name, data_type)

Block input port descriptor. This contains the name and data type of a block input port.

Arguments
  • name (string): Name
  • data_type (type|function): Data type, e.g. radio.types.ComplexFloat32, or a function predicate
Example
local inputs = {radio.block.Input("in1", radio.types.ComplexFloat32),
                radio.block.Input("in2", radio.types.ComplexFloat32)}
local outputs = {...}
...
self:add_type_signature(inputs, outputs)

Output

radio.block.Output(name, data_type)

Block output port descriptor. This contains the name and data type of a block output port.

Arguments
  • name (string): Name
  • data_type (type): Data type, e.g. radio.types.ComplexFloat32
Example
local inputs = {...}
local outputs = {radio.block.Output("out", radio.types.ComplexFloat32)}
...
self:add_type_signature(inputs, outputs)

Block

radio.block.Block()

Block base class.

Block:add_type_signature(inputs, outputs[, process_func=nil, initialize_func=nil])

Add a type signature.

Arguments
  • inputs (array): Input ports, array of radio.block.Input instances
  • outputs (array): Output ports, array of radio.block.Output instances
  • process_func (function): Optional process function for this type signature, defaults to process()
  • initialize_func (function): Optional process initialization for this type signature, defaults to initialize()
Raises
  • Invalid input port descriptor error.
  • Invalid output port descriptor error.
  • Invalid type signature, input count mismatch error.
  • Invalid type signature, input name mismatch error.
  • Invalid type signature, output count mismatch error.
  • Invalid type signature, output name mismatch error.
Block:differentiate(input_data_types)

Differentiate this block to a type signature.

Arguments
  • input_data_types (array): Array of input data types
Raises
  • No compatible type signatures found error.
Block:get_input_type([index=1])

Get the differentiated input data type.

Arguments
  • index (int): Index of input, starting at 1
Returns
  • Array of data types (array)
Raises
  • Block not yet differentiated error.
Block:get_output_type([index=1])

Get the differentiated output data type.

Arguments
  • index (int): Index of output, starting at 1
Returns
  • Data type (data_type)
Raises
  • Block not yet differentiated error.
Block:get_rate()

Get the block rate.

Returns
  • Block rate in samples per second (number)
Raises
  • Block not yet differentiated error.
Block:__tostring()

Get a string representation with the block name and port connectivity.

Returns
  • String representation (string)
Block:instantiate()

Instantiate hook, default no-op implementation.

Block:initialize()

Initialize hook, default no-op implementation.

Block:process()

Process hook, default implementation raises a not implemented error.

Block:cleanup()

Cleanup hook, default no-op implementation.


radio.block.factory(name[, parent_class=nil])

Block class factory.

Arguments
  • name (string): Block name
  • parent_class (class): Inherited parent class
Example
local MyBlock = radio.block.factory("MyBlock")

function MyBlock:instantiate(a, b)
    self.param = a + b

    self:add_type_signature({radio.block.Input("in", radio.types.Float32)},
                            {radio.block.Output("out", radio.types.Float32)})
end

function MyBlock:initialize()
    -- Differentiated data type and sample rate dependent initialization
end

function MyBlock:process(x)
    return x
end

Debug

Debug logging support.

radio.debug.enabled

bool: Debug logging enabled.


radio.debug.print(s)

Debug print.

Arguments
  • s (string): String to print

radio.debug.printf(...)

Debug formatted print.

Arguments
  • ...: Format string and arguments

Platform

Platform constants.

radio.platform.luajit_version

string: LuaJIT version (e.g. “LuaJIT 2.0.4”).


radio.platform.os

string: Operating System (e.g. “Linux”, “OSX”, “BSD”).


radio.platform.arch

string: Architecture (e.g. “x64”, “x86”, “arm”).


radio.platform.page_size

int: Page size (e.g. 4096).


radio.platform.cpu_count

int: CPU count (e.g. 4).


radio.platform.cpu_model

int: CPU model (e.g. “Intel(R) Core(TM) i5-4570T CPU @ 2.90GHz”).


radio.platform.alloc

function: Platform page-aligned allocator function.


radio.platform.features.liquid

bool: Liquid-dsp library found and enabled.


radio.platform.features.volk

bool: VOLK library found and enabled.


radio.platform.features.fftw3f

bool: FFTW3F library found and enabled.