/*********************************************************************** * work function **********************************************************************/ void SpectrogramDisplay::work(void) { auto updateRate = this->height()/_timeSpan; if (updateRate != _lastUpdateRate) this->callVoid("updateRateChanged", updateRate); _lastUpdateRate = updateRate; auto inPort = this->input(0); if (not inPort->hasMessage()) return; const auto msg = inPort->popMessage(); //label-based messages have in-line commands if (msg.type() == typeid(Pothos::Label)) { const auto &label = msg.convert<Pothos::Label>(); if (label.id == _freqLabelId and label.data.canConvert(typeid(double))) { this->setCenterFrequency(label.data.convert<double>()); } if (label.id == _rateLabelId and label.data.canConvert(typeid(double))) { this->setSampleRate(label.data.convert<double>()); } } //packet-based messages have payloads to FFT if (msg.type() == typeid(Pothos::Packet)) { const auto &buff = msg.convert<Pothos::Packet>().payload; auto floatBuff = buff.convert(Pothos::DType(typeid(std::complex<float>)), buff.elements()); //safe guard against FFT size changes, old buffers could still be in-flight if (floatBuff.elements() != this->numFFTBins()) return; //handle automatic FFT mode if (_fftModeAutomatic) { const bool isComplex = buff.dtype.isComplex(); const bool changed = _fftModeComplex != isComplex; _fftModeComplex = isComplex; if (changed) QMetaObject::invokeMethod(this, "handleUpdateAxis", Qt::QueuedConnection); } //power bins to points on the curve CArray fftBins(floatBuff.as<const std::complex<float> *>(), this->numFFTBins()); const auto powerBins = _fftPowerSpectrum.transform(fftBins, _fullScale); this->appendBins(powerBins); } }
void PeriodogramDisplay::work(void) { for (auto inPort : this->inputs()) { if (not inPort->hasMessage()) continue; const auto msg = inPort->popMessage(); //label-based messages have in-line commands if (msg.type() == typeid(Pothos::Label)) { const auto &label = msg.convert<Pothos::Label>(); if (label.id == _freqLabelId and label.data.canConvert(typeid(double))) { this->setCenterFrequency(label.data.convert<double>()); } if (label.id == _rateLabelId and label.data.canConvert(typeid(double))) { this->setSampleRate(label.data.convert<double>()); } } //packet-based messages have payloads to FFT if (msg.type() == typeid(Pothos::Packet)) { const auto &buff = msg.convert<Pothos::Packet>().payload; auto floatBuff = buff.convert(Pothos::DType(typeid(std::complex<float>)), buff.elements()); //safe guard against FFT size changes, old buffers could still be in-flight if (floatBuff.elements() != this->numFFTBins()) continue; //power bins to points on the curve CArray fftBins(floatBuff.as<const std::complex<float> *>(), this->numFFTBins()); const auto powerBins = fftPowerSpectrum(fftBins, _window.call<std::vector<double>>("window"), _window.call<double>("power")); if (not _queueDepth[inPort->index()]) _queueDepth[inPort->index()].reset(new std::atomic<size_t>(0)); _queueDepth[inPort->index()]->fetch_add(1); QMetaObject::invokeMethod(this, "handlePowerBins", Qt::QueuedConnection, Q_ARG(int, inPort->index()), Q_ARG(std::valarray<float>, powerBins)); } } }