DAB software: Qt-DAB and friends


A note on DAB

DAB, Digital Audio Broadcasting, is the system of choice for digital radio in Europe and Australia. Transmissions take place in the old Band III, i.e. in the range from 174 .. 230 MHz. In this band, there is room for 39 channels, each with a width of 1.5 MHz. The bandwidth per channel allows transmission of a whole lot of services simultaneously (services are either data or audio services).

DAB can be transmitted in a Single Frequency Network (SFN), meaning that within a region more than one transmitter transmits the same signal. Other than with FM, where interference of transmitters on the same frequency should be avoided, with DAB the receiver can select the strongest signal and just decode that.

DAB is usually decoded from a sample stream of 2048000 samples per second, an SDR device will select the frequency for the selected channel, will filter out the channel and convert the analog signal into a samplestream of - in our case - 2048000 samples a second.

From a software point of view, the samplestream is organized in blocks of 2552 samples. Such a block contains of a prefix, the first 504 samples in the block and 2048 samples with "useful" data.

The blocks are organized as frames where a frame takes

  1. an additional null part, which takes 2656 samples, samples with al - almost zero amplitude;

  2. 76 data blocks, the first block with predefined data, used for synchronization, then three blocks implementing a FIC, Fast Information Channel, and the remaining ones implementing the MSC, Main Service Channel.

A frame takes 199608 samples, with a samplerate of 2048000 samples a second, there are just over 10 frames a second.

The FIC blocks in the frame contain (the encoding of) a precise description of the elements encoded in the MSC. Things like name and location of the data in the MSC, and the way the data is encoded are all in the FIC.

The MSC blocks contain the encodings of the data of the services that are transmitted.

As discussed elsewehere, the decoder - once the beginning of the frames and blocks is established - reads in the blocks, removes the prefix of each block and feeds feeds the blocks into an FFT processor to translate the time domain samples into frequency domain values (carriers).

The 2048 complex carriers, resulting from the fft operation contain 256 empty values on each side, so there are 1536 complex values that contain the data contributong to the content/ From these 1536 values, we extract 3072 (soft) bits by looking at the phase difference of each value and the corresponding value in the preceding block. The phase difference then is translated into a value in the range -N .. N, where -N is a "definite" 1 bit and the N a "definite" 0 bit.

the bits - per group - are then processed by a viterbi decoder to get "real" bits.

There is a difference between DAB and DAB+. While the underlying technique is the same, i.e. for DAB and DAB+ the transmission of bits is the same, there is a huge difference in organizing the data.

Service data for DAB services is easy found, the FIC tells where the segments are to be found and what their length is. The segments are extracted and fed into an MP 2 decoder.

Service data for DAB+ services needs some additional processing steps before it can be fed into an AAC decoder. A DAB+ frame (not to be confused with the earlier mentioned frames), consist of 5 segments the address and length of which is given by the FIC.

These 5 segments are packed into a single DAB+ frame, the frame is divided into segments of 120 bytes that are protected with Reed-Solomon error recovery. Each 120 byte segment carries 10 parity byte with which up to 5 byte errors can be corrected. A full DAB+ frame then consist of 2, 3, 4 or 6 AAC frames. Of course, the AAC frames carry a CRC.


The picture shows details for an audio service. It shows that the offset where to find the data for this service is 252 units, each unit being 16 bytes. The size of the segment is 72 units, and the bitrate for the audio is 96 kBits per second. (It also shows that the transmission can be heard on FM as well).

What is also shown here is that the Reed-Solomon correction corrected 210 errors in the last 100 segments (which actually is quite a lot).

A few bits in the AAC frame are reserved for so-called Program Associated Data (PAD). PAD data is usually the Dynamic Label Text, and often some form of a Picture Label. At the bottom of the picture it states that MOT decoding is on, i.e. the PAD contains pictures.


Of course, next to audio services, DAB provides a variety of data services, the most well-known being the EPG and TPEG services.

An EPG service contains data for an Electronic Program Guide, TPEG is a protocol for traffic and trafix related information. TPEG is usually encripted.

A note on the DAB decoder

The decoder gets as input a sample stream, in our case the sample stream has a rate of 2048000 samples a seconds (although a version with 2 * 2048000 samples a second was also experimented with).

As menstioned, DAB is often transmitted in a single frequency network. Obviously these transmitters are synchronized, but the null period contains an encoding of the identification of the transmitter. The picture shows the spectrum of the null period, one sees a pattern of 4 values, repeated 4 times.


The advantage of covering an area with more than a single transmitter is of course that the transmitters can use limited power,


The picture shows the synchronization of a locally received signal, the two peaks show two transmitters nearby (which is correct, distance between my home and the transmitters is less than 15 km).

It shows that data of the second transmitter arrives app 40 samples earlier than data of the transmitter with the highest peak. This makes sense, the strongest transmitter is app 6 km further away from my home than the second one (power of the strongest transmitter is a 7 kw, the other a 1 kw transmitter).

As with DRM, the first question that needs to be solved is which sample in the incoming sample stream is the first sample of a DAB frame. DAB helps us here with the null period, app 2600 samples, with an amplitude of (almost) zero. So, just looking at a transition from a low power signal to a high(er) power signal will give a reasonable idea where the first data block following the null part starts.


Looking at the amplitudes of the signal in the null period and the first data block, one sees the double peaks in the amplitudes of the first block, apparantly two strong signals reached the receiver.

The first data block in a DAB frame contains predefined data, so correlating this data with the data of the first data block found after the null period, helps in detecting the exact position of the first sample in the incoming data block.

Of course, since it is known that a DAB frame takes 199608 samples, once the first sample of the first data block of a DAB frame is known, there is no need to check for the next frame for a transition from a low power signal to a hig(er) power signal, just after the 199608 samples of the frame passed, the data of the first block of the next DAB frame can be collected and subjected to a correlation check.

Frequency synchronization is an issue. Other than DRM, the spectrum of a DAB data block does not contain "pilot" like cells. However, the structure of the predefined data in the first datablock of the DAB frames offers solution for the coarse frequency synchronization.

As with DRM, the prefix in the time domain DAB blocks can be used to compute the small frequency offset. To eliminate noise, the small frequency offset is computed over a number of data blocks in the DAB frame.

As mentioned, the data blocks 2, 3 and 4 contain FIC data, the FFT processed output of these block are handed over to a FIC processor, a processor that maintains a data base structure with a decription of all elements in the transmission.

DAB data is encoded in two dimensions. i.e. in the complex domain. The picture shows an "ideal" signal, one clearly sees the 4 dots, corresponding to the values (1, 1), (1, -1), (-1, 1) and (-1, -1).


Whenever a user selects a service, another processor is fed with a description of the service (i.e. where to find the data, how to interpret the data etc), and a backend processor is instantiated. For audio and data there are different types of backend processors.

Such a backend processor takes the incoming bits, does the required interleaving and deconvolving and passes the resulting data on to a specific processor, for DAB Audio an MP2 processor, for DAB+ an MP4 processor etc. These processors will -using MP2 or AAC decoding libraries - generate PCM samples to be fed into the soundcard of the computer.

Of course, if there is PAD data, the MP2 or MP4 processor will extract the PAS data and pass it on to a PAD processor.

DAB software

Creating DAB software was a "learning experience" - (some of) the resulting main components being:

  1. Qt-DAB as the most extensive with controls and settings for everything for DAB decoding. The repository, containing sources and executables for both Qt-DAB and dabMini is here . Qt-DAB supports - depending on the selections in the configuration - SDRplay RSP's, AIRspy devices, Hackrf devices, Lime SDR devices, Adalm Pluto devices and - almost obviously - DABsticks.

  2. dabMini as the simple dab decoder for just selecting a service, built from the same set of sources as Qt-DAB;

  3. dab-cmdline as a library providing the functionality for decoding DAB accompanied with a number of example programs showing how to use it to create a command line based program as DAB decoder. The repository, containing the sources and a description how to use is here .

  4. webDAB, a DAB server with a minimal WEB client , sources are here

  5. eti-stuff as a simple program to generate ETI output from a received DAB transmission. The sources can be found here .

  6. channel-scanner as a simple command line driven program to (continuously) scan over specified channels, report on the contents of these channels and - if as option selected - record a number of seconds of the incoming data into a file. The sources can be found here .

Of course these programs take their input from any of a selection of SDR devices, depending on the configuration. The devices that can be included in the configuration are the devices I have (access to). To make life easy, for Qt-DAB and dabMini an appImage is available for running under x86_64 Linux and and installer is available for installing and running under Windows. For the others, one has to create an executable.

Sources are - obviously - also available, see the repositories on github ("https://github.com/JvanKatwijk/").



The picture shows the main widget of the Qt-DAB program. The program was built with the idea of being in control, i.e. the ability to see elements of the signal, and the ability to select parameters was the basis of the design. Therefore, this main widget contains buttons to show - or hide - other widgets.


This second picture shows - next to the station label - all additional widgets, the (in)visibility of which can be set indivuidually by a button on the main widget.

For Qt-DAB an extended user's guide is available here. The guide contains a detailed explanation of the GUI elements, a description of the device widgets for devices that can be configured, an extensive description of what to configure for a build, a description of how to build an executable, and even a description of how to interface another device.

users guide

Just to get acquainted with the transmitting capabilities of the Adalm Pluto, a configuration option exists (Linux only) for using an adapted version of the Pluto driver software. With this version - and on selecting the Pluto device as SDR device - the audio of the selected service is transmitted in stereo FM, augmented with the text of the dynamic label if the service as RDS text.


Built from the same set of sources, dabMini is a version of the DAB decoder with a minimal interface. The idea is that from time to time I just want to see the basic functionality, i.e. selecting a channel and a service and the ability to scan through the list of services. Some features, presets, the scheduler and the possibility for storing the dynamic label texts are included in the implementation.

users guide

A DAB library

To provide some flexibility, the functionality for DAB decoding, is also implemented in a separate library. The library can be build as a dynamic load library, or alternatively, the sources of the library can be included in a program. The use of the library is shown in a number of example programs.

The library contains just a few functions

	void DAB_API    *dabInit   (deviceHandler       *,
                            API_struct          *,
                            RingBuffer> *spectrumBuffer,
                            RingBuffer> *iqBuffer,
                            void                *userData);

	void DAB_API    dabExit         (void *);
	void DAB_API    dabStartProcessing (void *);
	void DAB_API	dabReset	(void *);
	void DAB_API	dabStop		(void *);
	void DAB_API	dabReset_msc		(void *);
	void DAB_API	dataforAudioService	(void *, const char *, audiodata *, int);
	void DAB_API	set_audioChannel	(void *, audiodata *);

Of course, the library sends data back, using callback functions, passed on in the API\_struct. The ringbuffers passed as parameter - if not specified to be null - are used to pass spectrum data and data to make the constellation of the decoded signal visible.

The most common example can be configured with any of SDRplay, AIRspy, dabsticks, LimeSDR, Hackrf, Adalm Pluto or file input. The resulting program is then command line based, e.g.

      dab-sdrplay-2 -M 1 -B "BAND III" -C 12C -P "Radio 4" -G 80 -A default

The line shows the invocation of example 2, configured with the SDRplay as SDR device, selecting Mode 1 (which is default), Band III (which is default), channel 12C, service "Radio 4", setting the gain to 80 (range 0 .. 100), and sound device is default.

Based on user requests, an additional example was created that binds a main program written in Python to a (special, binary version of the) library.

DAB server and WEB client

I sometimes run a DAB decoder on a simple (headless) RPI 3, controlling it from my laptop. I was figuring out a way to have the decoder run disconnected from my laptop, allowing establishing a connection when I wanted to adapt a setting (such as selecting another channel or service). Connection preferably from any laptop or tablet that I am using, so a WEB interface seemed logical. The result is webDAB, a small server with a minimal interface, an interface when a channel can be set, a service can be selected, gain for the device can be set and audio gain can be controlled.


Currently, the DAB server can be configured to run with the SDRplay and RT2832 based DAB sticks. Interfacing to any of the other devices for which dab-cmdline provides an interface is (almost) trivial.