A small and simple library for basic signal generation, processing and software defined radio implemented in C.
Written to learn about DSP and SDR.
- Sine, square, triangle and sawtooth Periodic functions.
- ADSR and raised-cosine Envelope function.
- Parameterized Wave from periodic function and envelope.
- Sampler to take samples from a Wave.
- PCM Frame to handle the samples.
- Gain applies gain to a frame.
- Oscillator producing real or complex (IQ) signal.
- Fft using Ooura's FFT implementations.
- FrameWriter to write frames to a file.
- FrameReader to read frames from a file or socket.
- FramePlayer to play frames to sound card.
- Demodulator for SSB/CW and AM.
- Demodulator for FM.
- Modulator for SSB/CW, AM and FM.
- AGC automatic gain control.
- FrameRecorder to record frames from sound card.
- Stft to create waterfall displays etc.
- Rectangular, Hamming or Hanning Window.
- Goertzel algorithm for DTMF detection.
- Waypoint periodic function.
Depends on portaudio and rtl-sdr.
sudo port install portaudio rtl-sdr
make
make test
gcc -I../src/include -lportaudio ../out/libNami.a play_sdr.c -o play_sdr
The library provide a few building blocks.
| Periodic function | ( -1 <= y <= 1, 0 <= x <= 2π )
|
\---------------> * <--------- | Envelope |
|
V
| Wave | <- f, phase, A
|
V
| Sampler | <- sampling frequency, t1, t2
|
V
| Frame | <- encoding
|
V
| FrameWriter |
| FrameReader |
|
V
| Frame |
|
V
FFT()
|
V
ComplexNumber[] ComplexNumber[]
| |
\---------*---------/
|
V
IFFT()
|
V
| Frame |
| FrameRecorder |
|
V
| Frame |
|
V
| AGC | | Oscillator |
| |
\--> | Demodulator | <---/
|
V
| Frame | -> | Stft | -> | ComplexFrame |
|
V
| FramePlayer |
| FrameRecorder | | FrameReader |
| |
V V
| Frame | | Frame |
| |
\--------------*-------------/
|
...
|
V
/--------------*-------------\
| |
| FramePlayer | | FrameWriter |
Periodic periodic;
Envelope envelope;
RaisedCosineParameters params;
Wave wave;
Sampler sampler;
Frame frame;
FrameWriter writer;
uint8_t data[FRAME_SIZE] = {0};
double angularFrequency = nami_angular_frequency_from_frequency(700);
params.rise_time = 0.020;
params.fall_time = 0.020;
params.sustain_time = 0.040;
nami_set_function(&periodic, &nami_sine_wave);
nami_set_envelope_function(&envelope, nami_raised_cosine, (void*)¶ms);
nami_set_periodic(&wave, &periodic, 0.5, 0, angularFrequency);
nami_set_envelope(&wave, &envelope);
nami_init_sampler(&sampler, &wave, 0, 0.080, SAMPLE_RATE);
nami_init_frame(&frame, UINT8, &data, FRAME_SIZE);
nami_open_writer(&writer, "morse_dit.raw");
while (nami_samples_left(&sampler) > 0) {
nami_fill_frame(&sampler, &frame);
nami_write_frame(&writer, &frame);
}
nami_close_writer(&writer);
Waveform as viewed in Audacity:
Periodic periodic;
Envelope envelope;
RaisedCosineParameters params;
Wave wave;
Sampler sampler;
Frame frame;
FrameWriter writer;
uint8_t data[FRAME_SIZE] = {0};
double angularFrequency = nami_angular_frequency_from_frequency(700);
params.rise_time = 0.016;
params.fall_time = 0.016;
params.sustain_time = 0;
nami_set_function(&periodic, &nami_sine_wave);
nami_set_envelope_function(&envelope, nami_raised_cosine, (void*)¶ms);
nami_set_periodic(&wave, &periodic, 0.5, 0, angularFrequency);
nami_set_envelope(&wave, &envelope);
nami_init_sampler(&sampler, &wave, 0, 0.032, SAMPLE_RATE);
nami_init_frame(&frame, UINT8, &data, FRAME_SIZE);
nami_open_writer(&writer, "psk31_zeros.raw");
for (int i = 0; i < 40; i++) {
while (nami_samples_left(&sampler) > 0) {
nami_fill_frame(&sampler, &frame);
nami_write_frame(&writer, &frame);
}
wave.phase += M_PI;
nami_set_current_sample_time(&sampler, 0);
}
nami_close_writer(&writer);
Waveform as viewed in Audacity:
- https://en.wikipedia.org/wiki/Wave
- https://en.wikipedia.org/wiki/Waveform
- http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
- http://www.portaudio.com/docs.html
- http://sdr.osmocom.org/trac/wiki/rtl-sdr
- http://www.dspguru.com/sites/dspguru/files/QuadSignals.pdf
- http://www.digitalsignallabs.com/Digradio.pdf