mirror of https://github.com/hmatuschek/libsdr
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.8 KiB
C++
107 lines
2.8 KiB
C++
#ifndef SCHUMANN_HH
|
|
#define SCHUMANN_HH
|
|
|
|
#include <libsdr/sdr.hh>
|
|
#include <libsdr/gui/gui.hh>
|
|
|
|
class Schumann: public sdr::gui::SpectrumProvider, public sdr::Sink<int16_t>
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
explicit Schumann(QObject *parent=0)
|
|
: sdr::gui::SpectrumProvider(parent), sdr::Sink<int16_t>(),
|
|
_buffer_idx(0), _avg_count(0), _buffer(2048), _spectrum(2048),
|
|
_spec_count(0), _avg_spectrum(2048), _subsample(0), _Fs(0), _fft(_buffer, sdr::FFT::FORWARD)
|
|
{
|
|
// init spectrum and buffer
|
|
for (size_t i=0; i<2048; i++) {
|
|
_buffer[i] = 0;
|
|
_spectrum[i] = 0;
|
|
}
|
|
}
|
|
|
|
virtual ~Schumann() {
|
|
// pass...
|
|
}
|
|
|
|
void config(const sdr::Config &src_cfg) {
|
|
// Requires type, sample rate & buffer size
|
|
if (!src_cfg.hasType() || !src_cfg.hasSampleRate() || !src_cfg.hasBufferSize()) { return; }
|
|
|
|
// Check buffer type
|
|
if (sdr::Config::typeId< int16_t >() != src_cfg.type()) {
|
|
sdr::ConfigError err;
|
|
err << "Can not configure Schumann: Invalid type " << src_cfg.type()
|
|
<< ", expected " << sdr::Config::typeId<int16_t>();
|
|
throw err;
|
|
}
|
|
|
|
// Check input sample rate
|
|
double Fs = src_cfg.sampleRate();
|
|
if (40 > Fs) {
|
|
sdr::ConfigError err;
|
|
err << "Can not configure Schumann: Input sample rate too low! The Schumann node requires at "
|
|
<< "least a sample rate of 40Hz, got " << Fs << "Hz";
|
|
throw err;
|
|
}
|
|
|
|
// Compute subsample
|
|
_subsample = Fs/40; _Fs = Fs/_subsample;
|
|
}
|
|
|
|
void process(const sdr::Buffer<int16_t> &buffer, bool allow_overwrite) {
|
|
for (size_t i=0; i<buffer.size(); i++) {
|
|
// Add value to buffer
|
|
_buffer[_buffer_idx] += float(buffer[i])/((1<<15)*_subsample); _avg_count++;
|
|
// If subsample count is reached:
|
|
if (_avg_count == _subsample) { _buffer_idx++; _avg_count = 0; }
|
|
if (_buffer_idx < 2048) { _buffer[_buffer_idx] = 0; }
|
|
if (_buffer_idx == 2048) {
|
|
// Compute FFT and add to spectrum:
|
|
_fft();
|
|
_spec_count++;
|
|
for (size_t i=0; i<2048; i++) {
|
|
_spectrum[i] += _buffer[i].real()*_buffer[i].real() + _buffer[i].imag()*_buffer[i].imag();
|
|
_avg_spectrum[i] = 10*(_spectrum[i]/_spec_count);
|
|
std::cout << _avg_spectrum[i] << "\t";
|
|
}
|
|
std::cout << std::endl;
|
|
_buffer[0] = 0; _buffer_idx=0;
|
|
emit spectrumUpdated();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool isInputReal() const {
|
|
return true;
|
|
}
|
|
|
|
double sampleRate() const {
|
|
return _Fs;
|
|
}
|
|
|
|
size_t fftSize() const {
|
|
return 2048;
|
|
}
|
|
|
|
const sdr::Buffer<double> &spectrum() const {
|
|
return _avg_spectrum;
|
|
}
|
|
|
|
protected:
|
|
size_t _buffer_idx;
|
|
size_t _avg_count;
|
|
sdr::Buffer< std::complex<float> > _buffer;
|
|
sdr::Buffer< double > _spectrum;
|
|
size_t _spec_count;
|
|
sdr::Buffer< double > _avg_spectrum;
|
|
size_t _subsample;
|
|
double _Fs;
|
|
sdr::FFTPlan<float> _fft;
|
|
};
|
|
|
|
|
|
|
|
#endif // SCHUMANN_HH
|