MCPcopy Create free account
hub / github.com/aethersdr/AetherSDR / decodeFFT

Method decodeFFT

src/core/PanadapterStream.cpp:862–948  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

860// ─── FFT decode ──────────────────────────────────────────────────────────────
861
862void PanadapterStream::decodeFFT(const uchar* raw, int totalBytes, bool hasTrailer, quint32 streamId)
863{
864 static constexpr int FFT_SUBHEADER_BYTES = 12;
865 if (totalBytes < VITA49_HEADER_BYTES + FFT_SUBHEADER_BYTES) return;
866
867 const uchar* sub = raw + VITA49_HEADER_BYTES;
868 const quint16 startBin = qFromBigEndian<quint16>(sub + 0);
869 const quint16 numBins = qFromBigEndian<quint16>(sub + 2);
870 const quint16 binSize = qFromBigEndian<quint16>(sub + 4);
871 const quint16 totalBins = qFromBigEndian<quint16>(sub + 6);
872 const quint32 frameIndex = qFromBigEndian<quint32>(sub + 8);
873
874 if (numBins == 0 || binSize == 0 || totalBins == 0) return;
875
876 const int binDataOffset = VITA49_HEADER_BYTES + FFT_SUBHEADER_BYTES;
877 int binDataBytes = numBins * binSize;
878 const int available = totalBytes - binDataOffset - (hasTrailer ? 4 : 0);
879 if (available < binDataBytes) {
880 binDataBytes = available;
881 if (binDataBytes <= 0) return;
882 }
883
884 const uchar* binData = raw + binDataOffset;
885
886 // Per-stream frame assembly
887 auto& frame = m_frames[streamId];
888 if (frameIndex != frame.frameIndex) {
889 if (frame.totalBins > 0 && !frame.isComplete())
890 PerfTelemetry::instance().recordFrameRestart(PerfTelemetry::FrameKind::Panadapter);
891 frame.reset(frameIndex, totalBins);
892 }
893
894 if (startBin + numBins > static_cast<quint16>(frame.buf.size()))
895 return;
896
897 for (quint16 i = 0; i < numBins; ++i)
898 frame.buf[startBin + i] = qFromBigEndian<quint16>(binData + i * 2);
899
900 frame.binsReceived += numBins;
901
902 if (!frame.isComplete()) return;
903
904 // Convert to dBm using per-stream range
905 QPair<float,float> dbmRange;
906 int yPixVal;
907 {
908 QMutexLocker lock(&m_streamMutex);
909 dbmRange = m_dbmRanges.value(streamId, {-130.0f, -40.0f});
910 yPixVal = m_yPixels.value(streamId, 700);
911 }
912 auto [minDbm, maxDbm] = dbmRange;
913 const float range = maxDbm - minDbm;
914 if (range <= 0.0f) return;
915
916 const int count = frame.buf.size();
917 QVector<float> bins(count);
918
919 int effectiveYPixels = std::max(yPixVal, 2);

Callers

nothing calls this directly

Calls 6

recordFrameRestartMethod · 0.80
isCompleteMethod · 0.45
resetMethod · 0.45
sizeMethod · 0.45
valueMethod · 0.45
enabledMethod · 0.45

Tested by

no test coverage detected