This objects implements a multi-channel DDC.


This feature is available only with a License - Contact us for more details


  • When using the GPU-Enabled SDRVM, the full process is offloaded to the GPU; input samples are pushed to the GPU and the different channels are processed in the GPU by specific tasks;
  • When using a non-GPU SDRVM, this is handled via the host processor.

It handles the starting/stopping of the attached SDR automatically:

  • When one channel is started, the radio is turned on,
  • As long as at least one channel is used, the radio remains on,
  • It stops when no channel is used.


Important note: The DDC only implements integer resampling. It means that the SDR sampling rate and the channel sample rate have to be chosen so that the ratio channel_rate / sdr_rate is integer.
For other ratios, one would have to use the simple DDC object that accepts rational ratios.

For optimization purposes, the filter coefficients computed on channel allocation are stored in RAM and may be reused if another channel is needed with the same decimation factor.

Object DDCBank {
    // connect the DDCBank to a receiver
    constructor DDCBank( JSRadio rx, int max_channels [default = 8 ] ) ;
    // connect the DDCBank to an input IQQueue
    constructor DDCBank( IQQueue input, number SampleRate, int max_channels [default = 8 ] ) ;

    bool setRFInputChannel( channel ); // configure the channel number in the source, default is 0 - use -1 to have all channels
    DDCBankChannel [or boolean false on fail] createChannel( int sample_rate_HZ  );
    bool hasSpareChannel();
    Array getChannels();

    bool shutdown(); // stops all

Constructors for DDCBank

Two differents constructors are available:

  • DDCBank fed by a JSReceiver, for automatic connection to a receiver;
  • DDCBank fed by a IQQueue, when the samples pushed from another task. In this case, the sampling rate MUST be known and provided.

In both cases, the number of channels is specified at allocation time and cannot be changed.

DCBank fed by a JSReceiver:

var gpuddc = new DDCBank( myrx, 16 );

DCBank fed by a IQQueue object:

var sampling_rate = 1e6 ;
var queue = IQQueues.create('input_queue');
var gpuddc = new DDCBank( queue, sampling_rate, 16 );


If the receiver has multiple channels, it is possible to configure which RF Channel has to be used for input.
For the BladeRF receiver, the intputs are mapped as follows:

  • RXA is channel 0,
  • RXB is channel 1.
  • Special case: use -1 to have all RF inputs in the same DDC (one DDC per RF channel) (see example below)

Example :

var rx = BladeRF.makeDevice({"device_name" : "bladerf"});
rx.setGain( 50 ) ;

var channels = rx.getChannelCount(); 
if( channels != 2 ) {
    print('We need two channels, we have : ' + channels) ;

var gpuddc = new DDCBank( myrx, 8 );

It is also possible to create a "multichannel" DDC : for example you want to have both RXA and RXB in the output stream:

var rx = BladeRF.makeDevice({"device_name" : "bladerf"});
rx.setGain( 50 ) ;

var gpuddc = new DDCBank( myrx, 8 );
gpuddc.setRFInputChannel( -1 );
var channel = gpuddc.createChannel( 100e3 );
channel.setOffset(  50e3 );

IQ blocks you will received out of DDC channel will contains both RF inputs. Then, use ".part()" member function to extract :

    var iq = channel.getIQ(true);
    var L = iq.getLength();
    var rx0_iq = iq.part(0, L, 0);
    var rx1_iq = iq.part(0, L, 1);


Allocate - if possible - a new channel in the DDC Bank. The given sample rate is the desired sample rate...
The DDC object will use the closest samplerate that is an integer fraction of the SDR source sample rate.

The returned value is a string containing the VM-Wide UNIQUE Identifier (UUID) of this channel. It will be possible to instanciate the DDC channel in another task by using this id (see DDC Bank channel).

var gpuddc = new DDCBank( myrx, 16 );

var channel_1 = gpuddc.createChannel( 100e3 );


Returns true if there are spare channels.


Returns a list of all the channels that have been created in the DDC.


Last update: December 23, 2022