Multi-source signal generator (msource)
API Keywords: msource multi-source source signal generator siggen
The msource family of objects are used to generate signals useful for testing communications systems. The interface allows for creating as many overlapping signals as you want, and provides a simple way to adjust their power level and center frequency independently with sample-level granularity.
Interface∞
The msource object allows you to create the following signal types:
- id = msourcecf_add_tone(q) : add a discrete DC tone. To set the frequency of the tone, use the 'set frequency' method (see below for details)
- id = msourcecf_add_noise(q, bw) : add a noise source with a two-sided bandwidth bw .
- id = msourcecf_add_modem(q,ms,k,m,beta) : add a modulated data stream with the modulation scheme specified by ms , and interpolated with a square-root Nyquist filter ( LIQUID_FIRFILT_ARKAISER ) with k samples per symbol, a filter delay of m symbols, and an excess bandwidth factor beta . Internally the data stream is created with the symstream object.
You may add as many signal types as you like using the methods described above. Each invocation returns an integer identifier as a handle for manipulating properties of that particular signal type. For example, you may set the following properties for any signal type:
- msourcecf_set_gain(q,id,gain_dB) : set the signal gain in dB
- msourcecf_set_frequency(q,id,dphi) : set the signal's angular frequency relative to the sample rate. The value of dphi ranges from \(-\pi\) to \(\pi\) .
Additionally you may easily enable/disable each signal type using the following methods:
- msourcecf_enable(q,id) : enable signal
- msourcecf_disable(q,id) : disable signal
Generate samples to an output buffer of any size with msourcecf_write_samples(q,buf,buf_len) . When you're done with a signal, you can remove it from the object list with the msourcecf_remove(q,id) method.
Example∞
The following listing demonstrates generating various signal types using the msourcecf object:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <liquid/liquid.h>
// user-defined callback; generate tones
int callback(void * _userdata,
float complex * _v,
unsigned int _n)
{
unsigned int * counter = (unsigned int*)_userdata;
unsigned int i;
for (i=0; i<_n; i++) {
_v[i] = *counter==0 ? 1 : 0;
*counter = (*counter+1) % 8;
}
return 0;
}
int main()
{
// msource parameters
int ms = LIQUID_MODEM_QPSK; // linear modulation scheme
unsigned int m = 12; // modulation filter semi-length
float beta = 0.30f; // modulation filter excess bandwidth factor
float bt = 0.35f; // GMSK filter bandwidth-time factor
// create multi-signal source generator
msourcecf gen = msourcecf_create_default();
// add signals (gen, fc, bw, gain, {options})
msourcecf_add_noise(gen, 0.0f, 1.00f, -40); // wide-band noise
msourcecf_add_noise(gen, 0.0f, 0.20f, 0); // narrow-band noise
msourcecf_add_tone (gen, -0.4f, 0.00f, 20); // tone
msourcecf_add_modem(gen, 0.2f, 0.10f, 0, ms, m, beta); // modulated data (linear)
msourcecf_add_gmsk (gen, -0.2f, 0.05f, 0, m, bt); // modulated data (GMSK)
unsigned int counter = 0;
msourcecf_add_user (gen, 0.4f, 0.15f, -10, (void*)&counter, callback); // tones
// print source generator object
msourcecf_print(gen);
// create spectral periodogram for estimating power spectral density
unsigned int nfft = 1200;
spgramcf periodogram = spgramcf_create_default(nfft);
unsigned int buf_len = 1024;
float complex buf[buf_len];
// generate 50 buffers worth of samples
unsigned int i;
for (i=0; i<50; i++) {
// write samples to buffer
msourcecf_write_samples(gen, buf, buf_len);
// push resulting sample through periodogram
spgramcf_write(periodogram, buf, buf_len);
}
// compute power spectral density output
float psd[nfft];
spgramcf_get_psd(periodogram, psd);
for (i=0; i<nfft; i++)
printf(" %12.8f %12.4e\n", (float)i/(float)nfft-0.5f, psd[i]);
// destroy objects
msourcecf_destroy(gen);
spgramcf_destroy(periodogram);
return 0;
}